Essential C++--Exercise of Chpt.4

本文记录了阅读《Essential C++》第四章后完成的练习,涉及Header文件使用、Stack类扩展、新类定义如UserProfile和Matrix。详细介绍了每个练习的实现,包括增加新功能、成员操作以及类的设计与实现。
摘要由CSDN通过智能技术生成

前言

  本文用于记录阅读书籍《Essential C++》Chpt.4后完成课后习题。


正文(Code)

4.1 First Meeting with Header File

  建立stack.hstack.suffix,此处的suffix是你的编译器所能接受的扩展名,或是你的项目所使用的扩展名。编写main()函数,练习操作Stack的所有公开接口,并加以编译执行。程序代码文件和main()都必须包含stack.h

#include <iostream>
#include <string>

#include "stack.h"

using namespace std;

bool get_another_try()
{
	char c_in;
	bool bTry;
	
	cout << "try it? (Y/y:yes N/n:no): ";
	cin >> c_in;

	bTry = ('Y' == c_in || 'y' == c_in);

	if (!bTry && 'N' != c_in && 'n' != c_in)
	{
		cout << "invalid input: " << c_in << endl;
	}

	return bTry;
}

int main()
{
	Stack stk;
	int r;

	r = init_stack(stk);
	if (0 != r)
	{
		cout << "init stack failed!" << endl;
		return -1;
	}

	string str_tmp;
	while(get_another_try())
	{
		cout << "pls input test choice(0:test pop, 1:test peek, 2:test empty, 3:test full): ";
		cin >> r;

		switch(r)
		{
			// test pop
			case 0:
			{
				if (!(stk.pop(str_tmp)))
				{
					cout << "test pop failed!" << endl;
					break;
				}
				cout << "get pop string: " << str_tmp 
					 << ", cur size: " << stk.size() << endl;
				break;
			}

			// test peek
			case 1:
			{
				if (!(stk.peek(str_tmp)))
				{
					cout << "test peek failed!" << endl;
					break;
				}
				cout << "get peek string: " << str_tmp
					 << ", cur size: " << stk.size() << endl;
				break;
			}

			// test empty
			case 2:
			{
				bool bEmpty = stk.empty();
				cout << "get empty: " << bEmpty
					 << ", cur size: " << stk.size() << endl;
				break;
			}

			// test full
			case 3:
			{
				bool bFull = stk.full();
				cout << "get full: " << bFull
					 << ", cur size: " << stk.size() << endl;
				break;
			}
			default:
			{
				cout << "invalid input: " << r
					 << ", cur size: " << stk.size() << endl;
				break;
			}
		}
	}

	cout << "user exit!" << endl;
	return 0;
}

  stack.cpp源文件如下所述:

#include "stack.h"

using namespace std;

bool
Stack::find(const string &str)
{
	vector<string>::iterator it = _stack.begin();

	while(it != _stack.end())
	{
		if (*it == str)
		{
			break;
		}

		it++;
	}

	return it != _stack.end();
}

int
Stack::count(const string &str)
{
	int cnt = 0;
	
	vector<string>::iterator it = _stack.begin();

	while(it != _stack.end())
	{
		if (*it == str)
		{
			cnt++;
		}

		it++;
	}

	return cnt;
}

int init_stack(Stack &stk)
{
	string str_arr[6] = {"a", "ab", "abc", "abcd", "abcde", "abcdef"};

	for(int i = 0; i < 6; i++)
	{
		stk.push(str_arr[i]);
	}
	
	return 0;
}

  stack.h头文件如下所述:

#ifndef _STACK_H_
#define _STACK_H_

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Stack
{
public:
	bool empty();
	bool full();
	bool peek(string &);
	bool pop(string &);
	bool push(const string &);

	bool find(const string &);
	int count(const string &);
	
	int size();

private:
	vector<string> _stack;
};

inline bool
Stack::empty(void)
{
	return _stack.empty();
}

inline bool
Stack::full(void)
{
	return (_stack.size() == _stack.max_size());
}

inline bool
Stack::peek(string &str)
{
	if (_stack.empty())
	{
		return false;
	}

	str = _stack.back();
	return true;
}

inline bool
Stack::pop(string &str)
{
	if (_stack.empty())
	{
		return false;
	}

	str = _stack.back();
	_stack.pop_back();
	return true;
}

inline bool
Stack::push(const string &str)
{
	_stack.push_back(str);
	return true;
}

inline int
Stack::size()
{
	return _stack.size();
}

int init_stack(Stack &stk);

#endif

4.2 Expand Class Stack

  扩展Stack的功能,以支持find()count()两个操作。find()会查看某值是否存在而返回truefalsecount()返回某字符串的出现次数。重新实现练习4.1的main(),让它调用这两个函数。

#include <iostream>
#include <string>

#include "stack.h"

using namespace std;

bool get_another_try()
{
	char c_in;
	bool bTry;
	
	cout << "try it? (Y/y:yes N/n:no): ";
	cin >> c_in;

	bTry = ('Y' == c_in || 'y' == c_in);

	if (!bTry && 'N' != c_in && 'n' != c_in)
	{
		cout << "invalid input: " << c_in << endl;
	}

	return bTry;
}

int main()
{
	Stack stk;
	int r;

	r = init_stack(stk);
	if (0 != r)
	{
		cout << "init stack failed!" << endl;
		return -1;
	}

	string str_tmp;
	while(get_another_try())
	{
		cout << "pls input test choice(0:test pop, 1:test peek, 2:test empty, 3:test full, 4:test find, 5:test count): ";
		cin >> r;

		switch(r)
		{
			// test pop
			case 0:
			{
				if (!(stk.pop(str_tmp)))
				{
					cout << "test pop failed!" << endl;
					break;
				}
				cout << "get pop string: " << str_tmp 
					 << ", cur size: " << stk.size() << endl;
				break;
			}

			// test peek
			case 1:
			{
				if (!(stk.peek(str_tmp)))
				{
					cout << "test peek failed!" << endl;
					break;
				}
				cout << "get peek string: " << str_tmp
					 << ", cur size: " << stk.size() << endl;
				break;
			}

			// test empty
			case 2:
			{
				bool bEmpty = stk.empty();
				cout << "get empty: " << bEmpty
					 << ", cur size: " << stk.size() << endl;
				break;
			}

			// test full
			case 3:
			{
				bool bFull = stk.full();
				cout << "get full: " << bFull
					 << ", cur size: " << stk.size() << endl;
				break;
			}

			// test find
			case 4:
			{
				cout << "pls input string you wanna find: ";
				cin >> str_tmp;
				
				if (stk.find(str_tmp))
				{
					cout << "find string: " << str_tmp << ", from class stack" << endl;
				}
				else
				{
					cout << "not find string: " << str_tmp << endl;
				}
				break;
			}

			// test count
			case 5:
			{
				cout << "pls input string you wanna find: ";
				cin >> str_tmp;

				r = stk.count(str_tmp);

				cout << "find string: " << str_tmp << ", count: " << r << endl;
				break;
			}
			default:
			{
				cout << "invalid input: " << r
					 << ", cur size: " << stk.size() << endl;
				break;
			}
		}
	}

	cout << "user exit!" << endl;
	return 0;
}

  注:拓展后的stack.cppstack.h参考4.1小节。


4.3 Create A new Class Including Several Data

  考虑一下所定义的全局(global)数据:

	string program_name;
	string version_stamp;
	int version_number;
	int tests_run;
	int tests_passed;

  类代码如下所示:

#include <iostream>
#include <string>

using namespace std;

class UserProfile
{
public:
	string program_name;
	string version_stamp;
	int version_number;
	int tests_run;
	int tests_passed;
};

4.4 Create A new Class UserProfile

  一份“用户概况记录(user profile)”内含以下数据:登录记录、实际姓名、登入次数、猜过次数、猜对次数、等级—包括初级、中级、高级、专家,以及猜对百分比(可实时计算获得,或将其值存起来备用)。请写出一个名为UserProfileclass,提供以下操作:输入、输出、相等测试、不等测试。其constructor必须能够处理默认的用户等级、默认的登录名称("guest")。对于同样名为guest的多个用户,你如何保证每个guest有他自己独有的登录会话(login session),不会和其他人混淆?

#include <iostream>
#include <string>

#include "user_profile.h"

int main()
{
#if 1  // create an object, using default constructor
	cout << "===== demo_1: create a class object, by default constructor! ====" << endl;

	UserProfile user_profile;
	string level2str[] = {"low", "middle", "high", "expert"};

	cout << "user_name: " << user_profile.get_usr_name() << endl;
	cout << "user_level: " << level2str[user_profile.get_usr_level()] << endl;

	cout << "create object user_profile by default constructor end!" << endl;
	cout << endl;
#endif

#if 1  // input an object by istream
	cout << "===== demo_2: create a class object by istream! ====" << endl;

	UserProfile user_profile_1;

	cin >> user_profile_1;    // std in
	//user_profile_1.pr_obj();  // print object info

	cout << "create user_profile_1 end!" << endl;
	cout << endl;
#endif

#if 1  // output an object by ostream
	cout << "===== demo_3: output a class object by ostream! ====" << endl;

	cout << user_profile_1 << endl;

	cout << "output user_profile_1 end!" << endl;
	cout << endl;
#endif

#if 1  // equality function of class
	cout << "===== demo_4: equality test! ====" << endl;

	UserProfile user_profile_2;

	cin >> user_profile_2;	  // std in
	user_profile_2.pr_obj();  // print object info

	cout << "get equality result: " << (user_profile_2 == user_profile_1) << endl;
	cout << "equality test end!" << endl;
	cout << endl;
#endif

#if 1  // inequality function of class
	cout << "===== demo_5: inequality test! ====" << endl;

	UserProfile user_profile_3;

	cin >> user_profile_3;	  // std in
	user_profile_3.pr_obj();  // print object info

	cout << "get inequality result: " << (user_profile_3 == user_profile_2) << endl;
	cout << "inequality test end!" << endl;
	cout << endl;
#endif

	cout << "demo end!" << endl;
	return 0;
}

  包含类UserProfile的头文件如下所述:

#ifndef _USER_PROFILE_H_
#define _USER_PROFILE_H_

#include <iostream>
#include <string>
#include <ctime>

using namespace std;

enum UserLevel_E
{
	low_level,
	middle_level,
	high_level,
	expert_level,
};

class UserProfile
{
public:
	UserProfile();  // default constructor
	
	friend ostream& operator<< (ostream &os, UserProfile &user_profile);
	friend istream& operator>> (istream &is, const UserProfile &user_profile);
	bool operator== (const UserProfile &user_profile);
	bool operator!= (const UserProfile &user_profile);

	// login_date
	string get_usr_login_date() {return _login_date;}
	int set_usr_login_date();

	// user_name
	string get_usr_name() {return _user_name;}
	int set_usr_name(const string &usr_name);

	// login_cnt
	int get_login_cnt() {return _login_cnt;}
	int set_login_cnt(const int &login_cnt);

	// user_guess_cnt
	int get_usr_guess_cnt() {return _user_guess_cnt;}
	int set_usr_guess_cnt(const int &usr_guess_cnt);

	// user_guess_correct_cnt
	int get_usr_guess_correct_cnt() {return _user_guess_correct_cnt;}
	int set_usr_guess_correct_cnt(const int &usr_guess_cor_cnt);

	// user_level
	UserLevel_E get_usr_level() {return _user_level;}
	int set_usr_level(const UserLevel_E &usr_level);

	// user_guess_percentage
	float get_usr_guess_percentage() {return _user_guess_percentage;}
	int set_usr_guess_percentage();

	void pr_obj() const;

private:
	string _login_date;
	string _user_name;
	int _login_cnt;
	int _user_guess_cnt;
	int _user_guess_correct_cnt;
	UserLevel_E _user_level;
	float _user_guess_percentage;
};

// constructor, default
inline UserProfile::UserProfile()
{
	_user_level = middle_level;
	_user_name = "guest";
}

inline bool
UserProfile::operator== (const UserProfile &user_profile)
{
	return (("guest" != this->_user_name) && (this->_user_name == user_profile._user_name));
}

inline bool
UserProfile::operator!= (const UserProfile &user_profile)
{
	return (this->_user_name != user_profile._user_name);
}

inline int 
UserProfile::set_usr_login_date()
{
	char str_buf[64];  // used for storing date-string
	
	// todo: get current date
	time_t tm;
	time(&tm);

	struct tm stTm;
	localtime_r(&tm, &stTm);
	
	// todo: convert into string
	strftime(str_buf, 64, "%Y-%m-%d %H-%M-%S", &stTm);

	this->_login_date = str_buf;
	return 0;
}

inline int 
UserProfile::set_usr_name(const string &usr_name)
{
	this->_user_name = usr_name;
	return 0;
}

inline int 
UserProfile::set_login_cnt(const int &login_cnt)
{
	this->_login_cnt = login_cnt;
	return 0;
}

inline int 
UserProfile::set_usr_guess_cnt(const int &usr_guess_cnt)
{
	this->_user_guess_cnt = usr_guess_cnt;
	return 0;
}

inline int 
UserProfile::set_usr_guess_correct_cnt(const int &usr_guess_cor_cnt)
{
	this->_user_guess_correct_cnt = usr_guess_cor_cnt;
	return 0;
}

inline int
UserProfile::set_usr_level(const UserLevel_E &usr_level)
{
	this->_user_level = usr_level;
	return 0;
}

inline int 
UserProfile::set_usr_guess_percentage()
{
	this->_user_guess_percentage = (this->_user_guess_cnt == 0 ? 0.0f : ((float)this->_user_guess_correct_cnt / (float)this->_user_guess_cnt));
	return 0;
}

inline void
UserProfile::pr_obj() const
{
	cout << *(UserProfile *)this << endl;
}

ostream& operator<< (ostream &os, UserProfile &user_profile)
{
	string level2str[] = {"low", "middle", "high", "expert"};

	os << "user_name: " << user_profile.get_usr_name() << '\n';
	os << "login_date: " << user_profile.get_usr_login_date() << '\n';
	os << "login_cnt: " << user_profile.get_login_cnt() << '\n';
	os << "user_guess_cnt: " << user_profile.get_usr_guess_cnt() << '\n';
	os << "user_guess_correct_cnt: " << user_profile.get_usr_guess_correct_cnt() << '\n';
	os << "user_level: " << level2str[user_profile.get_usr_level()] << '\n';
	os << "user_guess_percentage: " << user_profile.get_usr_guess_percentage();
	
	return os;
}

istream& operator>> (istream &is, UserProfile &user_profile)
{
	// input format: user_name, login_date, login_cnt, user_guess_cnt, user_guess_correct_cnt, user_level
	
	string usr_name;
	int login_cnt, usr_level;
	float usr_guess_cnt, usr_guess_cor_cnt;

	cout << "user_name: ";
	is >> usr_name;

	cout << "login_cnt: ";
	is >> login_cnt;

	cout << "user_guess_cnt: ";
	is >> usr_guess_cnt;

	cout << "user_guess_correct_cnt: ";
	is >> usr_guess_cor_cnt;

	cout << "user_level(0:low, 1:middle, 2:high, 3:expert): ";
	is >> usr_level;

	// update input into class object
	user_profile.set_usr_login_date();
	user_profile.set_usr_name(usr_name);
	user_profile.set_login_cnt(login_cnt);
	user_profile.set_usr_guess_cnt(usr_guess_cnt);
	user_profile.set_usr_guess_correct_cnt(usr_guess_cor_cnt);
	user_profile.set_usr_level((UserLevel_E)usr_level);
	user_profile.set_usr_guess_percentage();

	return is;
}
#endif

4.5 Create A new Class Matrix

  请实现一个4x4Matrix class,至少提供以下接口:矩阵加法、矩阵乘法、打印函数print()、复合运算符+=,以及一组支持下标操作(subscripting)function call运算符,像下面这样:

	float& operator() (int row, int column);
	float operator() (int row, int column) const;

  主进程调试源代码如下所述:

#include <iostream>
#include <string>

#include "matrix.h"

using namespace std;

int main()
{
#if 1  // create matrix obj 0, by default constructor
	cout << "=== create matrix obj 0, by default constructor ===" << endl;
	
	Matrix matrix_0;

	// dbg: print matrix info
	matrix_0.pr_matrix();
	
	cout << endl;
#endif

#if 1  // create matrix obj 1, using array which size if 16
	cout << "=== create matrix obj 1, using array which size if 16 ===" << endl;

	float arr[16] = {0,1,2,3,  4,5,6,7,  8,9,10,11,  12,13,14,15};
	Matrix matrix_1(arr);

	// dbg: print matrix info
	matrix_1.pr_matrix();

	cout << endl;
#endif

#if 1  // matrix add
	cout << "=== test matrix add ===" << endl;

	matrix_0.matrix_add(matrix_1);
	
	// dbg: print matrix info
	matrix_0.pr_matrix();

	cout << "test matrix add end!" << endl;
	cout << endl;
#endif

#if 1  // matrix multiple
	cout << "=== test matrix multiple ===" << endl;

	matrix_0.matrix_multi(matrix_1);

	// dbg: print matrix info
	matrix_0.pr_matrix();

	cout << "test matrix multiple end!" << endl;
	cout << endl;
#endif

#if 1
	cout << "=== test operator += ===" << endl;

	matrix_0 += matrix_1;

	// dbg: print matrix info
	matrix_0.pr_matrix();

	cout << "test operator += end!" << endl;
	cout << endl;
#endif

#if 1
	cout << "=== test subscripting ===" << endl;

	int row, col;
	cout << "input row(0~3): ";
	cin >> row;
	cout << "input column(0~3): ";
	cin >> col;
	
	// dbg: print matrix info
	float r = matrix_0(row, col);

	cout << "test subscripting end! get r: " << r << endl;
	cout << endl;
#endif

	cout << "demo end!" << endl;
	return 0;
}

  包含类Matrix定义的头文件Matrix.h如下所述:

#ifndef _MATRIX_H_
#define _MATRIX_H_

#include <iostream>
#include <string>

using namespace std;

class Matrix
{
public:
	Matrix();
	Matrix(float arr[16]);

	bool check_attr() const;      // check if attribute of object is valid, true:valid, false:invalid
	
	int matrix_add(Matrix &a);
	int matrix_multi(Matrix &a);
	void pr_matrix();
	int operator+=(Matrix &a);

	float& operator() (int row, int column);
	float operator() (int row, int column) const;
	
private:
	int _row;   // row of matrix, fixed
	int _col;   // column of matrix, fixed

	// todo: try using 2-d vector
	float _matrix_arr[4][4];  // vector<vector<float>> _matrix;
};

inline 
Matrix::Matrix()
{
	// initialize matrix size
	this->_row = 4;
	this->_col = 4;
	
	cout << "pls input default matrix(float): " << endl;

	for(int i = 0; i < this->_row; i++)
	{
		for(int j = 0; j < this->_col; j++)
		{
			cout << "(" << i << ", " << j << "): ";
			cin >> this->_matrix_arr[i][j];
		}
	}
}

inline 
Matrix::Matrix(float arr[16])
{
	// initialize matrix size
	this->_row = 4;
	this->_col = 4;

	for(int i = 0; i < this->_row; i++)
	{
		for(int j = 0; j < this->_col; j++)
		{
			this->_matrix_arr[i][j] = arr[i*this->_col + j];
		}
	}
}

inline bool
Matrix::check_attr() const
{
	return (this->_row == 4 && this->_col == 4);
}

inline int
Matrix::matrix_add(Matrix & a)
{
	if (!this->check_attr())
	{
		return -1;
	}
	
	for(int i = 0; i < this->_row; i++)
	{
		for(int j = 0; j < this->_col; j++)
		{
			this->_matrix_arr[i][j] += a._matrix_arr[i][j];
		}
	}
	
	return 0;
}

inline int
Matrix::matrix_multi(Matrix & a)
{
	if (!this->check_attr())
	{
		return -1;
	}
	
	for(int i = 0; i < this->_row; i++)
	{
		for(int j = 0; j < this->_col; j++)
		{
			this->_matrix_arr[i][j] *= a._matrix_arr[i][j];
		}
	}

	return 0;
}

inline void
Matrix::pr_matrix()
{
	if (!this->check_attr())
	{
		return;
	}

	for(int i = 0; i < this->_row; i++)
	{
		for(int j = 0; j < this->_col; j++)
		{
			cout << this->_matrix_arr[i][j] << " ";
		}
		cout << endl;
	}
}

inline int
Matrix::operator+= (Matrix &a)
{
	this->matrix_add(a);   // reuse function matrix_add
	return 0;
}

inline float& 
Matrix::operator() (int row, int column)
{
	if (!this->check_attr())
	{
		cout << "invalid obj attr! row: " << this->_row << ", col: " << this->_col << endl;
		return this->_matrix_arr[0][0];
	}

	if (row < 0 || row >= this->_row
		|| column < 0 || column >= this->_col)
	{
		cout << "invalid args! row: " << row << ", col: " << column << endl;
		return this->_matrix_arr[0][0];
	}
	
	return this->_matrix_arr[row][column];
}

inline float
Matrix::operator() (int row, int column) const
{
	if (!Matrix::check_attr())
	{
		cout << "invalid obj attr! row: " << this->_row << ", col: " << this->_col << endl;
		return this->_matrix_arr[0][0];
	}

	if (row < 0 || row >= this->_row
		|| column < 0 || column >= this->_col)
	{
		cout << "invalid args! row: " << row << ", col: " << column << endl;
		return this->_matrix_arr[0][0];
	}

	return this->_matrix_arr[row][column];
}
#endif

结语

  个人阅读书籍《Essential C++》之余创建此专栏,用于记录完成每一章节后附录的exercise。如有问题,请各位不吝指正。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SELECT t1.id, t1.[kh] AS '客户', t1.[lrsj] AS '录入时间', t1.[htbh] AS '合同编号', t1.[rq] AS '签订日期', t1.[htqsrq] AS '起始日期', t1.[htjzrq] AS '截止日期', t1.[zjey] AS '总金额', t1.[hjzld] AS '总吨数', t1.[lrsj] AS '创建时间', t1.[chpt] AS '撮合平台', CAST ( t1.[htwj] AS VARCHAR ( MAX ) ) AS '合同文件', STUFF( ( SELECT ',' + CONVERT ( VARCHAR, CASE WHEN ISNUMERIC( REPLACE( t2.ppcs, ',', '' ) ) = 1 THEN CAST ( REPLACE( t2.ppcs, ',', '' ) AS FLOAT ) END ) FROM uf_xsht_dt1 t2 WHERE t1.id = t2.mainid FOR XML PATH ( '' ) ), 1, 1, '' ) AS '品牌', STUFF( ( SELECT ' ' + CONVERT ( VARCHAR, CASE WHEN ISNUMERIC( REPLACE( t2.hsdjyd, ' ', '' ) ) = 1 THEN CAST ( REPLACE( t2.hsdjyd, ' ', '' ) AS FLOAT ) END ) FROM uf_xsht_dt1 t2 WHERE t1.id = t2.mainid FOR XML PATH ( '' ) ), 1, 1, '' ) AS '销售单价', (SELECT SUM ( sjfk ) from uf_xshksj2 WHERE cght=t1.id ) AS '实际已收', (SELECT SUM ( hkje ) from uf_xshksj2 WHERE cght=t1.id ) AS '已收货款', ( SELECT SUM( sjfk ) FROM uf_xshksj2 WHERE kxlx = 0 AND cght = t1.id ) AS '订金', CASE WHEN ((SELECT SUM (ISNULL( hkje,0) ) from uf_xshksj2 WHERE cght=t1.id ) + (SELECT SUM(ISNULL(sjfk, 0)) FROM uf_xshksj2 WHERE kxlx = 0 AND cght = t1.id)) < t1.[zjey] THEN ((SELECT SUM ( ISNULL( hkje,0)) from uf_xshksj2 WHERE cght=t1.id ) / t1.[zjey]) ELSE ((SELECT SUM ( ISNULL( hkje,0) ) from uf_xshksj2 WHERE cght=t1.id ) + (SELECT SUM(ISNULL(sjfk, 0)) FROM uf_xshksj2 WHERE kxlx = 0 AND cght = t1.id)) / t1.[zjey] END AS '已收比例' FROM uf_xsht t1 INNER JOIN uf_xsht_dt1 t2 ON t1.id = t2.mainid LEFT JOIN uf_xshksj2 t3 ON t1.id = t3.cght GROUP BY t1.id, t1.[kh], t1.[lrsj], t1.[htbh], t1.[rq], t1.[htqsrq], t1.[htjzrq], t1.[zjey], t1.[hjzld], t1.[chpt], CAST ( t1.[htwj] AS VARCHAR ( MAX ) )中为什么已付比例除了第一个有值 ,其他却显示空值
07-13
根据你提供的查询语句,我注意到在计算已付比例的部分使用了一个 CASE 表达式。首先,我想强调该查询语句中的子查询是分开计算的,每个子查询都会返回一个结果。而在 CASE 表达式中,只有第一个子查询的结果被用于计算已付比例,而其他子查询的结果没有被使用。这就是为什么其他部分显示为空值的原因。 如果你希望所有子查询的结果都被用于计算已付比例,你可以将这些子查询的结果提前计算并存储为临时表或使用内联视图。然后,在 CASE 表达式中引用这些临时表或内联视图,确保计算已付比例时所有子查询的结果都被考虑进去。 以下是一个示例,展示如何使用内联视图来计算已付比例: ```sql SELECT t1.id, t1.[kh] AS '客户', t1.[lrsj] AS '录入时间', -- 省略其他字段... CASE WHEN (t3.已收货款 + t3.订金) < t1.[zjey] THEN (t3.已收货款 / t1.[zjey]) ELSE (t3.已收货款 + t3.订金) / t1.[zjey] END AS '已收比例' FROM uf_xsht t1 INNER JOIN uf_xsht_dt1 t2 ON t1.id = t2.mainid LEFT JOIN ( SELECT cght, SUM(ISNULL(hkje, 0)) AS 已收货款, SUM(CASE WHEN kxlx = 0 THEN ISNULL(sjfk, 0) ELSE 0 END) AS 订金 FROM uf_xshksj2 GROUP BY cght ) t3 ON t1.id = t3.cght; ``` 在上述示例中,我使用了一个内联视图(子查询)来计算已收货款和订金的总和,并将其命名为 t3。然后,在 CASE 表达式中引用了 t3 中的已收货款和订金字段,确保计算已付比例时考虑了所有的子查询结果。 请根据你的实际需求和数据结构进行适当的调整。希望这能帮到你!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值