我正在尝试在我们的数据库中的一组装运条目上生成报告(月度,年初至今等),以显示正确的金额以及由运输公司对它们进行分组。如何完成所有这些信息并生成适当的报告?
需要注意的一点是,由于文本从各种来源导入了奇数字符,因此该表中的所有条目都是nvarchar(max)。
master数据库列表如下所示:
表 - shipping_info
shipping_company | ship_date | shipping_category | shipping_cost
UPS | 20130301 | CD'S | 3.50
UPS | 20130310 | Records | 4.50
UPS | 20130322 | CD'S | 7.50
UPS | 20130313 | Tapes | 12.44
UPS | 20130324 | CD'S | 3.50
UPS | 20120312 | Records | 4.50
UPS | 20120304 | CD'S | 5.50
UPS | 20120306 | Tapes | 3.50
UPS | 20130309 | CD'S | 3.50
USPS | 20130301 | Tapes | 3.50
USPS | 20130301 | CD'S | 5.50
USPS | 20130301 | CD'S | 4.50
USPS | 20130201 | Tapes | 3.50
USPS | 20130201 | CD'S | 3.50
USPS | 20130201 | Records | 7.50
USPS | 20130201 | Tapes | 9.50
USPS | 20130201 | CD'S | 12.50
USPS | 20120301 | CD'S | 14.50
USPS | 20120301 | Records | 3.50
USPS | 20130301 | CD'S | 23.50
USPS | 20120301 | Tapes | 15.50
USPS | 20120301 | CD'S | 34.50
DHL | 20120301 | Tapes | 35.50
DHL | 20120301 | CD'S | 3.50
DHL | 20130301 | Tapes | 3.50
DHL | 20130401 | CD'S | 3.50
DHL | 20130401 | Records | 4.50
DHL | 20130501 | CD'S | 4.50
DHL | 20120201 | Tapes | 5.50
DHL | 20120101 | CD'S | 6.50
DHL | 20120501 | CD'S | 3.50
DHL | 20120301 | Tapes | 7.50
我的目标是获得最终列表,该列表将按shipping_company打印已过滤的列表,即每月的总运费。在线下,我想获得一份年初至今的清单。无论如何,我希望看到月度报告发生的事情是这样的:
UPS Shipping Cost Report for March 2013
CD's - $23.50
Records - $9.00
Tapes - $15.94
我试过的是第一次
SELECT shipping_company, ship_date, shipping_category, shipping_cost FROM shipping_info WHERE (shipping_company = 'UPS' and shipping_cost IS NOT NULL and shipping_cost != '') GROUP BY shipping_company, ship_date, shipping_category, shipping_cost ORDER BY shipping_company, ship_date, shipping_category, shipping_cost
这产生了一个很好的过滤表,但我仍需要计算总和并按类别将总数分组。
然后我尝试了这个......
SELECT shipping_company, ship_date, shipping_category, SUM(shipping_cost) FROM shipping_info WHERE (shipping_company = 'UPS' and shipping_cost IS NOT NULL and shipping_cost != '') GROUP BY shipping_company, ship_date, shipping_category, shipping_cost ORDER BY shipping_company, ship_date, shipping_category, shipping_cost
由于这是一个NVARCHAR(MAX)表,t-sql因错误而告诉我需要将shipping_cost转换为int。
所以....我接下来试了这个。
SELECT shipping_company, ship_date, shipping_category, convert(decimal(10, 2), shipping_cost) FROM shipping_info WHERE (shipping_company = 'UPS' and shipping_cost IS NOT NULL and shipping_cost != '') GROUP BY shipping_company, ship_date, shipping_category, shipping_cost ORDER BY shipping_company, ship_date, shipping_category, shipping_cost
哪种工作和种类没有。
现在,当我将这个列表分解为可报告的段时,我对第一个示例中的哪个方向感到困惑。我是否正确地将我的信息纳入我需要的月度报告格式?
:: EDIT / UPDATE ::
这很棒,而且很有效。我花时间浏览了这段代码的每一步,现在我理解了这里发生的事情背后的理论。我最后还有一件事在这里磕磕绊绊。由于这个表是NVARCHAR(MAX),我遇到了一个挑战,试图让ship_date转换为数字而没有成功。
我采用了以下原始代码 - 示例1:
select
CASE WHEN (GROUPING(shipping_company) = 1) THEN 'TOTAL'
ELSE shipping_company END AS shipping_company,
CASE WHEN (GROUPING(SUBSTRING(ship_date, 1, 6)) = 1) THEN 'TOTAL'
ELSE SUBSTRING(ship_date, 1, 6) END AS Date,
CASE WHEN (GROUPING(shipping_category) = 1) THEN 'Yearly TOTAL'
ELSE shipping_category END AS shipping_category,
sum(convert(decimal(10,2),shipping_cost))
from tbl
group by shipping_company, SUBSTRING(ship_date, 1, 6),
shipping_category WITH rollup
然后添加数字转换命令,如下所示 - 示例2:
select
CASE WHEN (GROUPING(shipping_company) = 1) THEN 'TOTAL'
ELSE shipping_company END AS shipping_company,
CASE WHEN (GROUPING(CONVERT(numeric, (SUBSTRING(ship_date, 1, 6))) = 1) THEN 'TOTAL'
ELSE (CONVERT(numeric, SUBSTRING(ship_date, 1, 6))) END AS Date,
CASE WHEN (GROUPING(shipping_category) = 1) THEN 'Yearly TOTAL'
ELSE shipping_category END AS shipping_category,
sum(convert(decimal(10,2),shipping_cost))
from tbl
group by shipping_company, (CONVERT(numeric, SUBSTRING(ship_date, 1, 6))),
shipping_category WITH rollup
但仍然将nvarchar转换为数字错误。然后我就这样移动了 - 示例3:
select
CASE WHEN (GROUPING(shipping_company) = 1) THEN 'TOTAL'
ELSE shipping_company END AS shipping_company,
CASE WHEN (CONVERT(numeric, GROUPING(SUBSTRING(ship_date, 1, 6))) = 1) THEN 'TOTAL'
ELSE (CONVERT(numeric, SUBSTRING(ship_date, 1, 6))) END AS Date,
CASE WHEN (GROUPING(shipping_category) = 1) THEN 'Yearly TOTAL'
ELSE shipping_category END AS shipping_category,
sum(convert(decimal(10,2),shipping_cost))
from tbl
group by shipping_company, (CONVERT(numeric, SUBSTRING(ship_date, 1, 6))),
shipping_category WITH rollup
并得到'分组函数的参数1与GROUP BY子句中的任何表达式都不匹配'这是有意义的。我真的想学习背后的理论,不仅仅是为什么第二个例子不起作用,而是正确的行动方案可以使转换工作。
答案 0 :(得分:3)
尝试此查询
我从日期中提取了年份和月份部分,因此对特定年份的每个月进行分组。
select
shipping_company,
SUBSTRING(ship_date, 1, 6),
shipping_category,
sum(convert(decimal(10,2),shipping_cost))
from
tbl
group by
shipping_company,
SUBSTRING(ship_date, 1, 6),
shipping_category
| SHIPPING_COMPANY | COLUMN_1 | SHIPPING_CATEGORY | COLUMN_3 |
--------------------------------------------------------------
| DHL | 201201 | CD'S | 6.5 |
| DHL | 201202 | CD'S | 5.5 |
| DHL | 201203 | CD'S | 46.5 |
| DHL | 201205 | CD'S | 3.5 |
| DHL | 201303 | CD'S | 3.5 |
| DHL | 201304 | CD'S | 8 |
| DHL | 201305 | CD'S | 4.5 |
| UPS | 201203 | CD'S | 5.5 |
| UPS | 201203 | Records | 4.5 |
| UPS | 201203 | Tapes | 3.5 |
| UPS | 201303 | CD'S | 18 |
| UPS | 201303 | Records | 4.5 |
| UPS | 201303 | Tapes | 12.44 |
| USPS | 201203 | CD'S | 68 |
| USPS | 201302 | CD'S | 36.5 |
| USPS | 201303 | CD'S | 37 |
如果您想要每年的总数,那么您可以使用WITH ROLLUP
。
注意将年度总数视为每月总数...
查询1 :
select
CASE WHEN (GROUPING(shipping_company) = 1) THEN 'TOTAL'
ELSE shipping_company END AS shipping_company,
CASE WHEN (GROUPING(SUBSTRING(ship_date, 1, 6)) = 1) THEN 'TOTAL'
ELSE SUBSTRING(ship_date, 1, 6) END AS Date,
CASE WHEN (GROUPING(shipping_category) = 1) THEN 'Yearly TOTAL'
ELSE shipping_category END AS shipping_category,
sum(convert(decimal(10,2),shipping_cost))
from tbl
group by shipping_company, SUBSTRING(ship_date, 1, 6),
shipping_category WITH rollup
| SHIPPING_COMPANY | DATE | SHIPPING_CATEGORY | COLUMN_3 |
------------------------------------------------------------
| DHL | 201201 | CD'S | 6.5 |
| DHL | 201201 | Yearly TOTAL | 6.5 |
| DHL | 201202 | CD'S | 5.5 |
| DHL | 201202 | Yearly TOTAL | 5.5 |
| DHL | 201203 | CD'S | 46.5 |
| DHL | 201203 | Yearly TOTAL | 46.5 |
| DHL | 201205 | CD'S | 3.5 |
| DHL | 201205 | Yearly TOTAL | 3.5 |
| DHL | 201303 | CD'S | 3.5 |
| DHL | 201303 | Yearly TOTAL | 3.5 |
| DHL | 201304 | CD'S | 8 |
| DHL | 201304 | Yearly TOTAL | 8 |
| DHL | 201305 | CD'S | 4.5 |
| DHL | 201305 | Yearly TOTAL | 4.5 |
| DHL | TOTAL | Yearly TOTAL | 78 |
| UPS | 201203 | CD'S | 5.5 |
| UPS | 201203 | Records | 4.5 |
| UPS | 201203 | Tapes | 3.5 |
| UPS | 201203 | Yearly TOTAL | 13.5 |
| UPS | 201303 | CD'S | 18 |
| UPS | 201303 | Records | 4.5 |
| UPS | 201303 | Tapes | 12.44 |
| UPS | 201303 | Yearly TOTAL | 34.94 |
| UPS | TOTAL | Yearly TOTAL | 48.44 |
| USPS | 201203 | CD'S | 68 |
| USPS | 201203 | Yearly TOTAL | 68 |
| USPS | 201302 | CD'S | 36.5 |
| USPS | 201302 | Yearly TOTAL | 36.5 |
| USPS | 201303 | CD'S | 37 |
| USPS | 201303 | Yearly TOTAL | 37 |
| USPS | TOTAL | Yearly TOTAL | 141.5 |
| TOTAL | TOTAL | Yearly TOTAL | 267.94 |
确定您在更新的查询中遇到了问题。 If语句的两种情况都应返回相同的结果数据类型,因此当您尝试将日期值强制转换为数字时,您的真实案例将返回varchar
数据类型字段TOTAL
,而else字段返回{ {1}}输入字段,这会导致错误。
要解决此问题,您需要删除case语句,然后根据您的需要正常工作。
numeric
select
CASE WHEN (GROUPING(shipping_company) = 1) THEN 'TOTAL'
ELSE shipping_company END AS shipping_company,
CONVERT(numeric, (SUBSTRING(ship_date, 1, 6))) AS Date,
CASE WHEN (GROUPING(shipping_category) = 1) THEN 'Yearly TOTAL'
ELSE shipping_category END AS shipping_category,
sum(convert(decimal(10,2),shipping_cost))
from tbl
group by shipping_company, (CONVERT(numeric, SUBSTRING(ship_date, 1, 6))),
shipping_category WITH rollup
所以现在你必须在日期列中使用空值。希望这能解答你的疑虑。
希望这会有所帮助......