我正在制作产品库存并使用以下声明显示数据
SELECT _PRODNAME AS [Manufacture Product],
_BASEPRODNAME AS [Sub Product],
_PRDDEFQTY AS [Required Qty / Unit],
_PURQTY AS [Purchase Qty],
_PURRETQTY AS [Return Qty],
_ISSUEQTY AS [Issue Qty],
_DAMAGEQTY AS [Damage Qty],
_BALQTY AS [Balance Qty],
_MINESTIMATE AS [Estimate Qty],
_SALEQTY AS [Sale Qty],
_MANUDAMAGEQTY AS Damage,
_AVAILQTY AS [Avail Qty]
FROM dbo.VIEW_MANUFACTURING
此查询返回此结果:
但我的预期结果是
在我的样本数据中,Vanilla Cake是主要产品,Butter Cream,Eggs,Flour是子产品,3,4,5,6,7,8列是子产品数据,第9,10,11,12列是主要产品。
我的问题是如何单独显示这些数据,我对此一无所知。
编辑赏金
正如您在第一张图片中看到的,有两种制造产品1)Manu 2)Vanila Cake
这里我们将获得vanila蛋糕示例:
Vanila蛋糕有3个副产品1)黄油奶油2)鸡蛋3)面粉
第3至第8列与子产品(所需数量/单位列平衡数量列)相关
第9至12栏与制造产品相关(估算数量列到可用数量列)
预期结果显示在图2中
答案 0 :(得分:5)
您应该在应用程序层中进行此类操作。为什么? SQL表和结果集表示无序集 - 除非您专门指定排序。您尚未指定订购。
其次,SQL查询的所有列应具有相同的列数。您似乎想要为不同的行使用不同的数字。
一个部分解决方案是仅将名称放在“第一”行:
select (case when row_number() over (partition by _prodname order by _baseprodname) = 1
then _prodname
end) as [Manufacture Product],
. . .
from dbo.VIEW_MANUFACTURING
order by _prodname, _baseprodname;
要将它们放在不同的行上,您可以这样做:
select v.[Manufacture Product], v.[Sub Product], . . .
from (select vm.*,
row_number() over (partition by _prodname order by _baseprodname) as seqnum
from dbo.VIEW_MANUFACTURING vm
) vm outer apply
(values (1, _ProdName, NULL, NULL, . . .),
(2, NULL, _BaseProdName, . . .)
) v(seqnum, [Manufacture Product], [Sub Product], . . .)
where vm.seqnum = 1 or v.seqnum = 2
order by v.[Manufacture Product], v.seqnum, v.[Sub Product];
答案 1 :(得分:3)
在这个例子中,我选择了不属于“Manu”的独特产品。 (制造商)。为了确保所需输出的第一行的排序,我为行theOrder
赋予行一个整数= 1的子顺序。我查询了Manu'数据,假设您需要平均值,这是针对'香草蛋糕的制造商产品行。
我将所有这些与子产品详细信息联合起来,给它一个子序列int = 2,theOrder
。在您想要的输出中被删空的列我留下了NULL。
这整个事情都是subqueried,我做case语句来清空列,类似于你想要的输出。这是使用制造商产品名称和theOrder
列的组合订购的,因此应首先列出主要产品,然后列出子产品。
DECLARE @temp TABLE ([Manufacture Product] varchar(100), [Sub Product] varchar(100), [Required Qty / Unit] decimal(16,2), [Purchase Qty] decimal(16,2)
, [Return Qty] decimal(16,2)
,[Issue Qty] decimal(16,2), [Damage Qty] decimal(16,2), [Balance Qty] decimal(16,2), [Estimate Qty] decimal(16,2)
,[Sale Qty] decimal(16,2), [Damage] decimal(16,2), [Avail Qty] decimal(16,2))
INSERT INTO @temp
VALUES ('manu', '2 GOOD' , 34.00, 502.00, 0.00, 0.00, 0.00, 502.00, 14.71, 0.00, 0.00, 14.71)
,('manu', 'CHOCO AL...', 34.00, 500.00, 0.00, 0.00, 0.00, 500.00, 14.71, 0.00, 0.00, 14.71)
,('Vanila Cake', 'Butter Cream', 10.00, 600.00, 0.00, 72.00, 0.00, 528.00, 52.80, 0.00, 0.00, 52.80)
,('Vanila Cake', 'Eggs' , 2.00,1000.00, 0.00, 37.00, 0.00, 963.00, 52.80, 0.00, 0.00, 52.80)
,('Vanila Cake', 'Flour' , 5.00, 0.00, 0.00, 0.00, 0.00, 500.00, 52.80, 0.00, 0.00, 52.80)
SELECT CASE WHEN theOrder = 1 THEN [Manufacture Product] ELSE '' END [Manufacture Product]
,CASE WHEN theOrder = 2 THEN [Sub Product] ELSE '' END [Sub Product]
,[Required Qty / Unit]
,[Purchase Qty]
,[Return Qty]
,[Issue Qty]
,[Damage Qty]
,[Balance Qty]
,[Estimate Qty]
,[Sale Qty]
,Damage
,[Avail Qty]
FROM (
SELECT DISTINCT
1 [theOrder]
,T.[Manufacture Product]
,'' [Sub Product]
,NULL [Required Qty / Unit]
,NULL [Purchase Qty]
,NULL [Return Qty]
,NULL [Issue Qty]
,NULL [Damage Qty]
,NULL [Balance Qty]
,(SELECT AVG(T2.[Estimate Qty]) FROM @temp T2 WHERE T2.[Manufacture Product] = 'Manu') [Estimate Qty]
,(SELECT AVG([Sale Qty]) FROM @temp T2 WHERE T2.[Manufacture Product] = 'Manu') [Sale Qty]
,(SELECT AVG([Damage]) FROM @temp T2 WHERE T2.[Manufacture Product] = 'Manu') [Damage]
,(SELECT AVG([Avail Qty]) FROM @temp T2 WHERE T2.[Manufacture Product] = 'Manu') [Avail Qty]
FROM @temp T
WHERE T.[Manufacture Product] <> 'Manu'
UNION ALL
SELECT 2 [theOrder]
,T.[Manufacture Product]
,T.[Sub Product]
,T.[Required Qty / Unit]
,T.[Purchase Qty]
,T.[Return Qty]
,T.[Issue Qty]
,T.[Damage Qty]
,T.[Balance Qty]
,NULL [Estimate Qty]
,NULL [Sale Qty]
,NULL [Damage]
,NULL [Avail Qty]
FROM @temp T
WHERE T.[Manufacture Product] <> 'Manu'
) AS dT
ORDER BY dT.[Manufacture Product], dT.theOrder, dT.[Sub Product]
其产生的输出类似于您所要求的输出。 NULLS可以由报告工具处理。
仅供参考,我在报告SSRS等工具时更容易做到这一点。如果是SSRS,我会为制造产品制作一个父列。
答案 2 :(得分:2)
我认为这可以作为空值替换为空字符串,并用于演示如何在Image2中看到。
按Case statement
排序可能会得到结果集,请检查并告诉我
WITH cte
AS (
SELECT _PRODNAME AS [Manufacture Product]
,NULL [Sub Product]
,NULL [Required Qty / Unit]
,NULL [Purchase Qty]
,NULL [Return Qty]
,NULL [Issue Qty]
,NULL [Damage Qty]
,SUM(_BALQTY) AS [Balance Qty]
,SUM(_MINESTIMATE) AS [Estimate Qty]
,SUM(_SALEQTY) AS [Sale Qty]
,SUM(_MANUDAMAGEQTY) AS Damage
,SUM(_AVAILQTY) AS [Avail Qty]
FROM dbo.VIEW_MANUFACTURING
GROUP BY _PRODNAME
UNION ALL
SELECT NULL AS [Manufacture Product]
,_BASEPRODNAME AS [Sub Product]
,NULL AS [Required Qty / Unit]
,NULL AS [Purchase Qty]
,NULL AS [Return Qty]
,NULL AS [Issue Qty]
,NULL AS [Damage Qty]
,NULL AS [Balance Qty]
,SUM(_MINESTIMATE) AS [Estimate Qty]
,SUM(_SALEQTY) AS [Sale Qty]
,SUM(_MANUDAMAGEQTY) AS Damage
,SUM(_AVAILQTY) AS [Avail Qty]
FROM dbo.VIEW_MANUFACTURING
GROUP BY _BASEPRODNAME
)
SELECT ISNULL([Manufacture Product], '') [Manufacture Product]
,ISNULL([Sub Product], '') [Sub Product]
,ISNULL([Required Qty / Unit], '') [Required Qty / Unit]
,ISNULL([Purchase Qty], '') [Purchase Qty]
,ISNULL([Return Qty], '') [Return Qty]
,ISNULL([Issue Qty], '') [Issue Qty]
,ISNULL([Damage Qty], '') [Damage Qty]
,ISNULL([Balance Qty], '') [Balance Qty]
,ISNULL([Estimate Qty], '') [Estimate Qty]
,ISNULL([Sale Qty], '') [Sale Qty]
,ISNULL(Damage, '') Damage
,ISNULL([Avail Qty], '') [Avail Qty]
FROM cte
ORDER BY
CASE WHEN [Sub Product] is null and [Manufacture Product] is not null then [Manufacture Product] END DESC
, CASE WHEN [Manufacture Product] IS NULL THEN [Sub Product] END
答案 3 :(得分:2)
如果我正确理解您的要求,这是您的问题的解决方案。
SELECT CASE WHEN record_type = 'Product' THEN _PRODNAME ELSE NULL END AS [Manufacture Product]
,CASE WHEN record_type = 'Sub Product' THEN _BASEPRODNAME ELSE NULL END AS [Sub Product]
,CASE WHEN record_type = 'Sub Product' THEN _PRDDEFQTY ELSE NULL END AS [Required Qty / Unit]
,CASE WHEN record_type = 'Sub Product' THEN _PURQTY ELSE NULL END AS [Purchase Qty]
,CASE WHEN record_type = 'Sub Product' THEN _PURRETQTY ELSE NULL END AS [Return Qty]
,CASE WHEN record_type = 'Sub Product' THEN _ISSUEQTY ELSE NULL END AS [Issue Qty]
,CASE WHEN record_type = 'Sub Product' THEN _DAMAGEQTY ELSE NULL END AS [Damage Qty]
,CASE WHEN record_type = 'Sub Product' THEN _BALQTY ELSE NULL END AS [Balance Qty]
,CASE WHEN record_type = 'Product' THEN _MINESTIMATE ELSE NULL END AS [Estimate Qty]
,CASE WHEN record_type = 'Product' THEN _SALEQTY ELSE NULL END AS [Sale Qty]
,CASE WHEN record_type = 'Product' THEN _MANUDAMAGEQTY ELSE NULL END AS [Damage]
,CASE WHEN record_type = 'Product' THEN _AVAILQTY ELSE NULL END AS [Avail Qty]
FROM (
SELECT _PRODNAME
,NULL AS _BASEPRODNAME
,NULL AS _PRDDEFQTY
,NULL AS _PURQTY
,NULL AS _PURRETQTY
,NULL AS _ISSUEQTY
,NULL AS _DAMAGEQTY
,NULL AS _BALQTY
,_MINESTIMATE
,_SALEQTY
,_MANUDAMAGEQTY
,_AVAILQTY
,'Product' AS record_type
FROM (
SELECT _PRODNAME
,_BASEPRODNAME
,_PRDDEFQTY
,_PURQTY
,_PURRETQTY
,_ISSUEQTY
,_DAMAGEQTY
,_BALQTY
,_MINESTIMATE
,_SALEQTY
,_MANUDAMAGEQTY
,_AVAILQTY
,'Product' AS record_type
,ROW_NUMBER() OVER (
PARTITION BY _PRODNAME ORDER BY _PRODNAME
) r_num
FROM dbo.VIEW_MANUFACTURING
) v
WHERE r_num = 1
UNION
SELECT _PRODNAME
,_BASEPRODNAME
,_PRDDEFQTY
,_PURQTY
,_PURRETQTY
,_ISSUEQTY
,_DAMAGEQTY
,_BALQTY
,_MINESTIMATE
,_SALEQTY
,_MANUDAMAGEQTY
,_AVAILQTY
,'Sub Product' AS record_type
FROM dbo.VIEW_MANUFACTURING
) v1
ORDER BY _PRODNAME ,
_BASEPRODNAME;
输出在这里
答案 4 :(得分:2)
<强>演示强>
<强> SQL 强>
SELECT _PRODNAME AS [Manufacture Product],
NULL AS [Sub Product],
NULL AS [Required Qty / Unit],
NULL AS [Purchase Qty],
NULL AS [Return Qty],
NULL AS [Issue Qty],
NULL AS [Damage Qty],
NULL AS [Balance Qty],
_MINESTIMATE AS [Estimate Qty],
_SALEQTY AS [Sale Qty],
_MANUDAMAGEQTY AS Damage,
_AVAILQTY AS [Avail Qty]
FROM dbo.VIEW_MANUFACTURING
WHERE _PRODNAME = 'Vanila Cake'
GROUP BY _PRODNAME, _MINESTIMATE, _SALEQTY, _MANUDAMAGEQTY, _AVAILQTY
UNION ALL
SELECT NULL AS [Manufacture Product],
_BASEPRODNAME AS [Sub Product],
_PRDDEFQTY AS [Required Qty / Unit],
_PURQTY AS [Purchase Qty],
_PURRETQTY AS [Return Qty],
_ISSUEQTY AS [Issue Qty],
_DAMAGEQTY AS [Damage Qty],
_BALQTY AS [Balance Qty],
NULL AS [Estimate Qty],
NULL AS [Sale Qty],
NULL AS Damage,
NULL AS [Avail Qty]
FROM dbo.VIEW_MANUFACTURING
WHERE _PRODNAME = 'Vanila Cake';
备注强>
可以使用DISTINCT
代替GROUP BY
甚至简单的SELECT TOP 1
。 GROUP BY
被选中,因为它比DISTINCT
更快,并且会突出显示非规范化数据的任何问题。
答案 5 :(得分:2)
您可以使用GROUPING SETS
(Demo)
SELECT [Manufacture Product] = _PRODNAME,
[Sub Product] = _BASEPRODNAME,
[Required Qty / Unit] = CASE WHEN GROUPING(_BASEPRODNAME) = 0 THEN SUM(_PRDDEFQTY) END,
[Purchase Qty] = CASE WHEN GROUPING(_BASEPRODNAME) = 0 THEN SUM(_PURQTY) END,
[Return Qty] = CASE WHEN GROUPING(_BASEPRODNAME) = 0 THEN SUM(_PURRETQTY) END,
[Issue Qty] = CASE WHEN GROUPING(_BASEPRODNAME) = 0 THEN SUM(_ISSUEQTY) END,
[Damage Qty] = CASE WHEN GROUPING(_BASEPRODNAME) = 0 THEN SUM(_DAMAGEQTY) END,
[Balance Qty] = CASE WHEN GROUPING(_BASEPRODNAME) = 0 THEN SUM(_BALQTY) END,
[Estimate Qty] = CASE WHEN GROUPING(_BASEPRODNAME) = 1 THEN SUM(_MINESTIMATE) END,
[Sale Qty] = CASE WHEN GROUPING(_BASEPRODNAME) = 1 THEN SUM(_SALEQTY) END,
Damage = CASE WHEN GROUPING(_BASEPRODNAME) = 1 THEN SUM(_MANUDAMAGEQTY) END,
[Avail Qty] = CASE WHEN GROUPING(_BASEPRODNAME) = 1 THEN SUM(_AVAILQTY) END
FROM dbo.VIEW_MANUFACTURING
GROUP BY GROUPING SETS ( ( _PRODNAME ), ( _PRODNAME, _BASEPRODNAME ) )
ORDER BY [Manufacture Product] ASC,
GROUPING(_BASEPRODNAME) DESC,
[Sub Product] ASC
如果需要,只需添加WHERE _PRODNAME = 'Vanila Cake'
。
或者你可以用
删除重复的CASE
表达式
WITH T
AS (SELECT [Manufacture Product] = _PRODNAME,
[Sub Product] = _BASEPRODNAME,
[Required Qty / Unit] = SUM(_PRDDEFQTY),
[Purchase Qty] = SUM(_PURQTY),
[Return Qty] = SUM(_PURRETQTY),
[Issue Qty] = SUM(_ISSUEQTY),
[Damage Qty] = SUM(_DAMAGEQTY),
[Balance Qty] = SUM(_BALQTY),
[Estimate Qty] = SUM(_MINESTIMATE),
[Sale Qty] = SUM(_SALEQTY),
Damage = SUM(_MANUDAMAGEQTY),
[Avail Qty] = SUM(_AVAILQTY),
GrpFlag = GROUPING(_BASEPRODNAME)
FROM VIEW_MANUFACTURING
GROUP BY GROUPING SETS ( ( _PRODNAME ), ( _PRODNAME, _BASEPRODNAME ) ))
SELECT T.[Manufacture Product],
T.[Sub Product],
OA1.*,
OA2.*
FROM T
OUTER APPLY (SELECT [Required Qty / Unit],[Purchase Qty],[Return Qty],[Issue Qty],[Damage Qty],[Balance Qty]
WHERE GrpFlag = 0) OA1
OUTER APPLY (SELECT [Estimate Qty],[Sale Qty], Damage, [Avail Qty]
WHERE GrpFlag = 1) OA2
ORDER BY [Manufacture Product] ASC,
GrpFlag DESC,
[Sub Product] ASC