我最初是想通过PHP来解决这个问题,但是我运气不好......
How Can I Merge All Duplicates In Array Based On One Key's Value?
由于我没有找到解决方案,我决定尝试通过SQL查询来解决我的问题。我需要知道的是如何“合并”此查询中返回的行之间的差异?
SELECT
Item.ID,
Item.ItemLookupCode,
nitroasl_pamtable.ManufacturerPartNumber,
SupplierList.ReorderNumber,
Item.Notes,
Item.Description,
Item.ExtendedDescription,
Item.Quantity,
nitroasl_pamtable.SpoofStock,
Item.Price,
nitroasl_pamtable.PAM_Keywords
FROM
Item
JOIN
nitroasl_pamtable ON Item.ID = nitroasl_pamtable.ItemID
JOIN
SupplierList ON Item.ID = SupplierList.ItemID
WHERE
(Item.ItemLookupCode LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR
(nitroasl_pamtable.ManufacturerPartNumber LIKE '%tp-ac1750%'
AND Price > 0.00 AND WebItem = 1)
OR
(SupplierList.ReorderNumber LIKE '%tp-ac1750%' AND Price > 0.00
AND WebItem = 1)
OR
(Item.Notes LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR
(Item.Description LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR
(Item.ExtendedDescription LIKE '%tp-ac1750%' AND Price > 0.00
AND WebItem = 1)
OR
(nitroasl_pamtable.PAM_Keywords LIKE '%tp-ac1750%' AND Price > 0.00
AND WebItem = 1)
ORDER BY
Item.ItemLookupCode ASC;
MySQL的GROUP_CONCAT等价物
我相信这个功能会做我需要的,但我使用的是SQL Server - 而不是MySQL。我似乎无法获得有关如何为我工作的发布解决方案......
最近,我尝试了MAX()
和GROUP BY
函数(一起),但它选择了重复行中返回的MAX
值,因此返回一行每列中MAX
个值。
SELECT
MAX(Item.ID) AS Id,
Item.ItemLookupCode,
MAX(nitroasl_pamtable.ManufacturerPartNumber) AS ManufacturerPartNumber,
MAX(SupplierList.ReorderNumber) AS ReorderNumber,
MAX( CAST(Item.Notes AS varchar(max)) ) AS Notes,
MAX(Item.Description) AS Description,
MAX( CAST(Item.ExtendedDescription AS varchar(max)) ) AS ExtendedDescription,
MAX(Item.Quantity) AS Quantity,
MAX(nitroasl_pamtable.SpoofStock) AS SpoofStock,
MAX(Item.Price) AS Price,
MAX(nitroasl_pamtable.PAM_Keywords) AS PAM_Keywords,
MAX(Item.PictureName) AS PictureName
FROM
Item
LEFT JOIN
nitroasl_pamtable ON Item.ID = nitroasl_pamtable.ItemID
LEFT JOIN
SupplierList ON Item.ID = SupplierList.ItemID
WHERE
(Item.ItemLookupCode LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (nitroasl_pamtable.ManufacturerPartNumber LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (SupplierList.ReorderNumber LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (Item.Notes LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (Item.Description LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (Item.ExtendedDescription LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (nitroasl_pamtable.PAM_Keywords LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
GROUP BY
Item.ItemLookupCode
ORDER BY
Item.ItemLookupCode ASC
我希望将每列的所有返回值(用MAX丢弃)放入由逗号分隔的各自/原始列中,而不是丢弃每列的变体...
在上面的文件中,您将看到上述SQL查询返回的四行。我希望返回一行,如下所示:
ID
8265
ItemLookupCode:
TP-AC1750
ManufacturerPartNumber:
Archer C7
ReorderNumber:
7681617, ARCHERC7, N82E16833704177
备注:
TP-LINK Archer C7 AC1750 Routr
说明
TP-LINK Archer C7 AC1750 Routr
ExtendedDescription:
TP-Link Archer C7 Wireless-AC1750 Dual-Band Gigabit Router
数量:
0 (This should actually be a combined sum/total of the values in this column)
SpoofStock:
NULL (Same as Quantity - Should be sum / This value is different than Quantity)
价格:
129.95
PAM_Keywords:
NULL
我知道有更好的方法来编写此查询。我不是一个SQL人。此查询/脚本是一个关键字搜索,它返回Microsoft Dynamics RMS数据库中的项目,并输出我用来创建可以更改并重新提交到数据库的产品列表的JSON。我使用SQL Server 2008 R2(如果重要的话)。有关如何使用我的查询的某些变体来完成上述输出的任何建议将不胜感激!感谢
以下是一个链接到SQLFiddle:)
SQLFiddle with No MAX Function
SQLFiddle with MAX Function(由于丢失数据,这不是一个可行的解决方案)
答案 0 :(得分:1)
这会让你开始,但nitroasl_pamtable
表格仍然存在一些不确定性,所以我没有把它包括在内。
SELECT
I.ID,
I.ItemLookupCode,
I.Notes,
I.Description,
I.ExtendedDescription,
I.Quantity,
I.Price,
SL.ReorderNumbers,
P.SpoofStock,
P.ManufacturerPartNumber,
P.PAM_Keywords
FROM
Item I
LEFT JOIN nitroasl_pamtable P
ON I.ID = P.ItemID
OUTER APPLY (
SELECT
ReorderNumbers = Substring((
SELECT DISTINCT Convert(varchar(max), ', ' + SL.ReorderNumber)
FROM SupplierList SL
WHERE I.ID = SL.ItemID
FOR XML PATH(''), TYPE
).value('.[1]', 'varchar(max)'), 3, 2147483647)
) SL
WHERE
I.Price > 0.00
AND I.WebItem = 1
AND (
I.ItemLookupCode LIKE '%tp-ac1750%'
OR I.Notes LIKE '%tp-ac1750%'
OR I.Description LIKE '%tp-ac1750%'
OR I.ExtendedDescription LIKE '%tp-ac1750%'
OR P.ManufacturerPartNumber LIKE '%tp-ac1750%'
OR P.PAM_Keywords LIKE '%tp-ac1750%'
OR EXISTS (
SELECT *
FROM dbo.SupplierList SL2
WHERE
I.ID = SL2.ItemID
AND SL2.ReorderNumber LIKE '%tp-ac1750%'
)
)
ORDER BY
I.ItemLookupCode ASC;
要正确引入nitroasl_pamtable
,对于要连接的每个列,您可以执行新的OUTER APPLY
。您可以执行单个OUTER APPLY
以立即获取需要正常聚合的所有列(例如Sum()
)。
但是,我想提出这种串联会以一种可能导致错误评估或决策的方式模糊数据。从表中提取3个值并连接/求和它们将使它们看起来是一个单位,这可能不正确。
连接可能有害的另一种方式是重新排序数字。请注意,由于两个重复的重新订购号码,我在其中放置了DISTINCT
- 但它们来自不同的供应商。那么除了可以从中获取供应商之外,重新订购号码还有什么用呢?如果两个不同的商品在不同的供应商处具有相同的再订货号怎么办? (例如,重新订购号BIGBOX
是一家供应商的电视,但它是另一家供应商的巨型纸板箱。)
我不相信在查询中连接这些值是个好主意。相反,UI应该单独显示查询(项目作为一个行集,然后将每个其他表的支持数据作为单独的行集),然后以在UI中有意义的方式呈现数据。
答案 1 :(得分:0)
如果我理解正确,看起来你只需要连接ReorderNumber
字段。您可以使用SQLCLR用户定义聚合(UDA)来完成此操作。
在SQLCLR函数,存储过程等SQL#库中有一个预先完成的UDA,称为 Agg_Join (我是作者,但是这个聚合函数)有免费版本)。使用它会使您的查询看起来如下:
SELECT
MAX(Item.ID) AS Id,
Item.ItemLookupCode,
MAX(nitroasl_pamtable.ManufacturerPartNumber) AS ManufacturerPartNumber,
SQL#.Agg_Join(SupplierList.ReorderNumber) AS ReorderNumber,
MAX( CAST(Item.Notes AS varchar(max)) ) AS Notes,
MAX(Item.Description) AS Description,
MAX( CAST(Item.ExtendedDescription AS varchar(max)) ) AS ExtendedDescription,
MAX(Item.Quantity) AS Quantity,
MAX(nitroasl_pamtable.SpoofStock) AS SpoofStock,
MAX(Item.Price) AS Price,
MAX(nitroasl_pamtable.PAM_Keywords) AS PAM_Keywords,
MAX(Item.PictureName) AS PictureName
FROM Item
LEFT JOIN nitroasl_pamtable
ON Item.ID = nitroasl_pamtable.ItemID
LEFT JOIN SupplierList
ON Item.ID = SupplierList.ItemID
WHERE
(Item.ItemLookupCode LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (nitroasl_pamtable.ManufacturerPartNumber LIKE '%tp-ac1750%'
AND Price > 0.00
AND WebItem = 1)
OR (SupplierList.ReorderNumber LIKE '%tp-ac1750%'
AND Price > 0.00
AND WebItem = 1)
OR (Item.Notes LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (Item.Description LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (Item.ExtendedDescription LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
OR (nitroasl_pamtable.PAM_Keywords LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1)
GROUP BY Item.ItemLookupCode
ORDER BY Item.ItemLookupCode ASC;
简而言之,SQL#的完整版包含一个更强大的 Agg_Join 版本,名为 Agg_JoinPlus ,允许排序,过滤掉重复项,替换{{1} },更改分隔符等。
或者,如果你想自己创建这个,在这种情况下你可以自定义功能,我写了一篇文章,展示了创建一个用户定义的聚合的例子,只需要稍微修改一下就可以了连接:Getting The Most Out of SQL Server 2005 UDTs and UDAs(需要免费注册)。这是在SQL Server 2008发布之前编写的,它能够将NULL
设置为MaxSize
,以便它一次可以存储超过8000个字节(这对于这种类型的问题更为重要)操作比许多算术运算都要好。)
另一个不需要订阅且开箱即用的选项(我自己没有尝试过)是这个开源项目:
GROUP_CONCAT string aggregate for SQL Server
此项目自2013-05-09以来尚未更新,但我怀疑它会做你想要的并且适合你的查询,就像 SQL#.Agg_Join 和任何其他聚合一样。在安装脚本文件夹中有一个安装脚本 GroupConcatInstallation.sql ,其中包含Assembly和T-SQL包装器对象。
是的,所有这些聚合都应该与PHP或其他任何东西一起使用,因为它们是查询的一部分,因此它是执行处理的SQL Server,它与任何特定的客户端软件无关。