SELECT 具有复合键的 DISTINCT

SELECT DISTINCT with composite key

这是对我遇到的问题的简化,但使用此示例我想获取给定客户的所有产品记录。 给客户可能有很多订单,有些订单可能是同一产品我不想拉回重复的产品。 产品 table 上还有一个复合键。

在理想情况下,这很简单,下面的查询就可以完成这项工作。然而,由于 table 包含一个 nText 列,SQL 服务器抱怨 "The ntext data type cannot be selected as DISTINCT because it is not comparable."

SELECT distinct p.idA, p.idB, p.descriptionNTEXT
FROM p product, o order, c customer
WHERE o.productID = p.idA AND o.subProductID = p.idB AND o.customerID = c.ID

我想将其重组为

SELECT p1.idA, p1.idB, p1.descriptionNTEXT
FROM   p1 product
WHERE (p1.idA, p1.idB) IN
   (
       SELECT p.idA, p.idB
       FROM p product, o order, c customer
       WHERE o.productID = p.idA AND o.subProductID = p.idB AND o.customerID = c.ID
   )

参见 How do I (or can I) SELECT DISTINCT on multiple columns?

但是这种方法不适用于 SQL 服务器

有什么想法吗?

理想情况下,我需要一个 portable 解决方案,它至少可以在 SQLServer、MySQL 和 Oracle 上运行。但是针对数据库的解决方案总比没有好!

下面的数据大概就是我想要的了

Customer
ID name
1  Fred

Order
ID  CustomerID productID subProductID
10  1          100       200
11  1          100       200
12  1          100       200
13  1          101       201

Product
IDA  IDB descriptionNTEXT
100  200 'product 1'
101  201 'product 2'    
102  203 'product 3'    

Expected Result
IDA  IDB descriptionNTEXT
100  200 'product 1'
101  201 'product 2'    

将 NTEXT 转换为 NVARCHAR(MAX)

SELECT distinct p.idA, p.idB, cast (p.descriptionNTEXT as nvarchar(max))
FROM p product, o order, c customer
WHERE o.productID = p.idA AND o.subProductID = p.idB AND o.customerID = c.ID

IMPORTANT! ntext, text, and image data types will be removed in a future version of SQL Server. Avoid using these data types in new development work, and plan to modify applications that currently use them. Use nvarchar(max), varchar(max), and varbinary(max) instead.

https://msdn.microsoft.com/en-us/library/ms187993.aspx


nvarchar [ ( n | max ) ] Variable-length Unicode string data. n defines the string length and can be a value from 1 through 4,000. max indicates that the maximum storage size is 2^31-1 bytes (2 GB). The storage size, in bytes, is two times the actual length of data entered + 2 bytes. The ISO synonyms for nvarchar are national char varying and national character varying.

https://msdn.microsoft.com/en-us/library/ms186939.aspx

先做distinct,再join products。

select p.*
    from (
        select distinct CustomerID, productID, subProductID
        from [Order]
    ) do
    join Product p on p.productID = do.IDA and p.subProductID = do.IDB

查看您的代码,您似乎想在多个字段上使用 IN - 这可以通过 EXISTS 实现 - 它询问指定的查询是否 returns 任何行 - 所以根据你的查询可能是像

SELECT p1.idA, p1.idB, p1.descriptionNTEXT
FROM   p1 product
WHERE EXISTS
   (
       SELECT 1
       FROM p product, o order, c customer
       WHERE o.productID = p.idA AND o.subProductID = p.idB AND o.customerID = c.ID 
             AND p1.idA = p.ida 
             AND p1.idB = p.idb
   )

您可以在不将其转换为另一种类型的情况下进行尝试

SELECT p1.idA, p1.idB, p1.descriptionNTEXT
from product p1 where p1.IDA in( SELECT Distinct p.idA FROM  product p,order o,customer c WHERE o.productID = p.idA AND o.subProductID = p.idB AND o.customerID = c.ID)