我最初试图通过PHP来解决这个问题,但是我没有太多的运气…
如何根据一个键's值合并数组中的所有重复项?
因为我没有找到一个解决方案,我决定尝试通过我的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,我用它来创建一个可以更改并重新提交到DB的产品列表。我使用SQL Server 2008 R2(如果有关系的话)。任何关于我如何使用我的查询的一些变化来完成上述输出的建议将非常感谢!由于
<标题>更新(SQLFiddle)这里有一个SQLFiddle的链接,可以使用:)
SQLFiddle with No MAX Function
SQLFiddle with MAX Function(不是一个可行的解决方案,因为我丢失了数据)
标题>这将让您开始,但仍然有一些不确定性围绕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应该分别显示查询(item作为一个行集,然后来自其他表的支持数据作为单独的行集),然后以在UI中有意义的方式显示数据。
如果我理解正确的话,看起来您只需要连接ReorderNumber
字段。您可以使用SQLCLR用户定义聚合(User-Defined Aggregate, UDA)来非常简单地完成此操作。
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,它允许排序,过滤重复,替换NULL
s,更改分隔符等。
或者,如果您想自己创建它,在这种情况下,您可以自定义功能,我写了一篇文章,展示了创建用户定义聚合的示例,只需稍微更改一下即可进行字符串连接:充分利用SQL Server 2005 udt和UDAs(需要免费注册)。这是在SQL Server 2008出来之前写的,它有能力将MaxSize
设置为-1
,这样它就可以一次存储超过8000字节(这对于这种类型的操作来说比许多算术运算更有问题)。
另一个不需要订阅并且应该开箱即用的选项(我自己没有尝试过)是这个开源项目:
GROUP_CONCAT string aggregate for SQL Server
这个项目自2013-05-09以来一直没有更新,但我怀疑它会做你想要的,并且会像SQL#一样适合你的查询。Agg_Join和任何其他聚合。有一个安装脚本,GroupConcatInstallation。sql,在包含Assembly和T-SQL包装器对象的Installation Scripts文件夹中。
是的,所有这些聚合应该与PHP或其他任何东西一起工作,因为它们是查询的一部分,因此它是SQL Server进行处理,它与任何特定的客户端软件无关。