2016-11-14 117 views
1

这是我对问题的简化,但是使用这个例子我想获得给定客户的所有产品记录。 给客户可能有很多订单和一些订单可能是针对同一个产品我不想拉回重复的产品。 产品表上还有一个组合键。SELECT DISTINCT with composite key

在一个理想的世界中,这很简单,下面的Query将完成这项工作。但是,由于表包含nText列,SQL Server会抱怨“ntext数据类型不能被选为DISTINCT,因为它不具有可比性。”

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服务器

任何想法上运行?

理想情况下,我需要一个可移植的解决方案,至少可以在SQLServer上工作,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'  
+1

添加一些示例表数据和预期的结果 - 以及格式化文本。 – jarlh

回答

2

看你的代码,你似乎想在多个领域使用IN - 这样就可以实现通过EXISTS - 询问是否指定的查询返回的任何行 - 所以根据您的查询,那么可能是这样的

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 
    ) 
+0

谢谢,这看起来像原始查询的干净重新分解,似乎是不会在查询上造成巨大开销的vanilla SQL。 – Sprotty

+0

不完全是我的用例,但'WHERE EXISTS(SELECT 1 ...)'的想法使我走向了正确的方向。非常聪明:) – ferdynator

6

演员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 

重要! ntext,文本和图像数据类型将在 未来版本的SQL Server中删除。避免在新的 开发工作中使用这些数据类型,并计划修改当前使用 的应用程序。改为使用nvarchar(max),varchar(max)和varbinary(max)。

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


nvarchar的[(N | MAX)]可变长度Unicode字符串数据。 n 定义了字符串的长度,可以是1到4,000的值。最大 表示最大存储大小为2^31-1个字节(2 GB)。存储大小(以字节为单位)是输入数据的实际长度的两倍 + 2个字节。 nvarchar的ISO同义词是国家字符变化和国家字符变化。

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

+0

谢谢,我想这会截断描述,如果在旧版SQL版本上超过4000/8000字符? 它还需要使用blob。 不幸的是避免使用类型不是一种选择,因为这是一个可以在第三方数据库上运行的工具。但很高兴知道被替换,它们始终是问题和不兼容的来源。 – Sprotty

+0

@Sprotty,nvarchar(最大)限制是2G(请参阅编辑答案)。对于BLOB使用varbinary(max)https://msdn.microsoft.com/en-us/library/ms188362.aspx –

+0

是由任何独特的IDA IDB组合提供的唯一性吗?这似乎是建立一个独特行的好方法 - 您的示例SQL似乎是在明智的行上,除非您不能在两个字段中使用IN - 但您可以切换到EXISTS(这将适用于零个,1个或多个字段) - 那么你可能不需要担心转换BLOB,ntext等 - 使用产品描述来确定唯一可能不是最好的方法。 – Cato

0

首先做不同的,然后再加入到产品。

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

我认为这看起来像一个合理的解决方案,虽然语法可能不是SQL服务器 - 但问题一般提到数据库 - 也许可以在downvoted时使用注释完成? – Cato

+0

@Cato我真的不希望这个确切的查询能在SQL Server中工作,但我相信它应该在原则上工作。我的查询的哪些部分不适用于SQL Server? –

+0

也许是'Product p on(p.productID,p.subProductID)=(do.IDA,do.IDB)'部分,或者它可能是我以前从未见过的,或者它是较新的SQL版本 – Cato

0

你可以试试这个而不将其转换为另一种类型

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) 
+0

这看起来像它可以与我提供的有限的测试数据一起工作,但如果IDA以不同的IDB值重复,将无法按预期工作。 – Sprotty

+0

我认为它会起作用 – mansi