选择具有多个不同列的整行

时间:2014-09-12 12:06:45

标签: sql select sql-server-2005 distinct greatest-n-per-group

我有一个基于发票项目的表格,我试图使用SQL来检测物料/客户组合的价格或货币在哪些日期发生变化。该表包含多个客户的发票,尽管这些材料可能很常见。

我的SQL技能非常基础,我尝试了几种不同的方法,使用了我在其他线程中找到的GROUP BY和DISTINCT,但我似乎总是被困在某个地方。

这基本上就是数据的样子:

Invoice Inv. Date   Material    Price   Currency    Per/Qty    Customer
SE100   20140901    111111         1      EUR           1       840006
SE100   20140901    222222         2      EUR         1000      840006
SE100   20140901    333333         3      USD           1       840006
SE101   20140902    111111         1      EUR           1       840006
SE101   20140902    222222         2      EUR         1000      840006
SE101   20140902    333333         3      USD           1       840006
SE102   20140903    111111         2      EUR           1       840006
SE102   20140903    222222         2      USD         1000      840006
SE102   20140903    333333         3      USD           1       840006
SE103   20140904    111111         1      EUR           1       840006
SE103   20140904    222222         2      USD         1000      840006
SE103   20140904    333333         3      USD           1       840006

我想要完成的基本上是为客户/物料/货币/价格的所有不同组合选择日期的第一行,然后为选择中出现多次的那些物料选择整个行(按材料排序) ,从而表明价格或货币已从初始值发生变化。

使用上表中的数据查询的预期输出将如下所示:

Invoice Inv. Date   Material    Price   Currency    Per/Qty    Customer
SE100   20140901    111111         1      EUR           1       840006
SE102   20140903    111111         2      EUR           1       840006
SE103   20140904    111111         1      EUR           1       840006
SE100   20140901    222222         2      EUR         1000      840006
SE102   20140903    222222         2      USD         1000      840006

我希望我能以一种可以理解的方式解释这个问题。数据库引擎是SQL Server 2005 Express。

任何帮助将不胜感激......

2 个答案:

答案 0 :(得分:0)

SQL中的关键字DISTINCT具有"唯一值"的含义。当应用于查询中的列时,它将从结果集中返回尽可能多的行,因为该列具有唯一的不同值。因此,它创建了一个分组结果集,其他列的值是随机的,除非由其他函数定义(例如max,min,average等)。

如果您想要返回Col 06具有特定值的所有行,请使用" where Col 06 = value"条款

SELECT  mt.*
FROM    (
    SELECT  DISTINCT col6
    FROM    mytable
    ) mto
JOIN    mytable mt
ON      mt.id = 
    (
    SELECT  TOP 1 id
    FROM    mytable mti
    WHERE   mti.col6 = mto.col6
    -- ORDER BY
    --      id
    --  Uncomment the lines above if the order matters
    )

答案 1 :(得分:0)

我认为这是你想要的直接翻译:

select t.*
from mydata t join
     (select Customer, Material, count(distinct price) as numprices
      from mydata
      group by Customer, Material
      having count(distinct price) > 1
     ) cmcp
     on t.customer = cmcp.customer and t.material = cmcp.material;

这就省去了货币。不幸的是,SQL Server不支持distinct的多个参数。您可以这样包含它:

select t.*
from mydata t join
     (select Customer, Material,
             count(distinct cast(price as varchar(255)) + ':' + currency) as numprices
      from mydata
      group by Customer, Material
      having count(distinct cast(price as varchar(255)) + ':' + currency)  > 1
     ) cmcp
     on t.customer = cmcp.customer and t.material = cmcp.material;

大多数数据库都支持窗口/分析函数,因此您也可以将其标记为:

select t.*
from (select t.*,
             min(cast(price as varchar(255)) + ':' + currency)) over (partition by Customer, Material) as minprice,
             max(cast(price as varchar(255)) + ':' + currency)) over (partition by Customer, Material) as maxprice
      from mydata t
     ) t
where minprice <> maxprice
order by Material, Inv_Date;