Sql 努力寻找正确的WHERE子句

Sql 努力寻找正确的WHERE子句,sql,sql-server-2008,ssrs-2008,Sql,Sql Server 2008,Ssrs 2008,我正在处理SQL查询,需要您的帮助。老实说,我开始怀疑我想实现的目标是否能像我目前所做的那样实现,但也许你的集体智慧能想出比我更好的解决方案,并证明我在一开始就采取了好的方式(或者我完全错了,我应该从头开始) 数据集 一行有4个重要字段:ItemID、Item、优先级和组。这些字段包含唯一有价值的信息,即最后将显示的信息 当我使用SQL Server 2008时,我无法访问LAG和LEAD函数,因此我需要模拟它们(或者至少,我这样做是因为我认为它对我有用,但我不再那么确定)。为了得到这个结果,我

我正在处理SQL查询,需要您的帮助。老实说,我开始怀疑我想实现的目标是否能像我目前所做的那样实现,但也许你的集体智慧能想出比我更好的解决方案,并证明我在一开始就采取了好的方式(或者我完全错了,我应该从头开始)

数据集 一行有4个重要字段:
ItemID
Item
优先级
。这些字段包含唯一有价值的信息,即最后将显示的信息

当我使用SQL Server 2008时,我无法访问
LAG
LEAD
函数,因此我需要模拟它们(或者至少,我这样做是因为我认为它对我有用,但我不再那么确定)。为了得到这个结果,我使用了代码,从中可以得到一个
LAG
LEAD
等价物,我将其限制为一组具有相同
ItemID
的行。这将向我的数据集中添加7个新的功能列:
Rn
RnDiv2
RnPlus1Div2
PreviousPriority
NextPriority
PreviousGroup
NextGroup

ItemID      | Item      | Priority  | Group     | Rn        | RnDiv2    | RnPlus1Div2   | PreviousPriority  | NextPriority  | PreviousGroup     | NextGroup 
--------    | -------   | --------  | -------   | -----     | ------    | -----------   | ----------------  | ------------  | -------------     | --------- 
16777397    | Item 1    | 5         | Group 1   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777403    | Item 2    | 5         | Group 2   | 1         | 0         | 1             | NULL              | 5             | NULL              | Group 2   
16777403    | Item 2    | 10        | Group 2   | 2         | 1         | 1             | 5                 | NULL          | Group 2           | NULL      
16777429    | Item 3    | 1000      | Group 3   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777430    | Item 4    | 5         | Group 1   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777454    | Item 5    | 5         | Group 4   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777455    | Item 6    | 5         | Group 5   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777459    | Item 6    | 5         | Group 6   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777468    | Item 8    | 5         | Group 7   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777479    | Item 9    | 5         | Group 4   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777481    | Item 10   | 5         | Group 4   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777496    | Item 11   | 5         | Group 6   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777514    | Item 12   | 5         | Group 4   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
16777518    | Item 13   | 5         | Group 8   | 1         | 0         | 1             | NULL              | 10            | NULL              | Group 8   
16777518    | Item 13   | 10        | Group 8   | 2         | 1         | 1             | 5                 | 100           | Group 8           | Group 1   
16777518    | Item 13   | 100       | Group 1   | 3         | 1         | 2             | 10                | NULL          | Group 8           | NULL      
16777520    | Item 14   | 5         | Group 9   | 1         | 0         | 1             | NULL              | NULL          | NULL              | NULL      
问题 SQL查询中的问题是
WHERE
子句。我将始终根据行的
列过滤行。但也有一些微妙之处。无论
一个
项目
的成员是多少,我希望它根据以下标准出现在一个且只有一个
中:

  • 如果
    项目
    多次出现在同一
    中,则只应返回优先级最低的
    行。如果
    项目
    在同一
    中多次出现,但具有相同的
    优先级
    ,则只应保留第一次出现的项目。例如:对于
    项目2
    ,只应返回
    优先级
    值为5的行
  • 如果
    项目出现在
    中,但也出现在另一个
    优先级最低的
    中,则不应显示该项目。示例:
    选择组1
    作为过滤器<代码>项目1
    应显示,但
    项目13
    不应显示,因为它也以较低的
    优先级出现在
    组8
    中(
    项目13
    仅出现在
    组8
    中)
  • 请注意,这只是一个示例。我的真实数据集有3000多行,其他一些情况可能我没有在示例中列出

    失败的尝试 就像我说的,
    WHERE
    子句中有一个常量,那就是
    过滤

    • 由于标准#2,我不能简单地这样开始我的子句:
      其中Group='group1'
      ,我需要一些更复杂的东西
    • 我尝试了以下子句但没有成功:
      其中Group='group1'和(Group=nextgroupandpriority
      。对于不超过2组的
      项目
      ,该方法效果良好。但是对于
      项目13
      ,它将返回前两行。如果我在
      WHERE
      子句中添加类似于
      和NOT(CorrectedPriority>=PreviousPriority)
      的内容,则根本不会得到任何结果
    • 到目前为止的最后一次尝试:
      (SiteName PreviousSiteName和CorrectedPriority>=PreviousPriority)
      。问题是我永远不会返回
      Rn=1
      的行,因为
      PreviousSiteName
      将等于
      NULL
      。在
      NULL
      上添加检查也不起作用。我在尝试这一条款时一定累了,因为它完全是垃圾
    我会继续努力找到good
    WHERE
    子句,但我觉得我的整个方法是错误的。当同一
    项有两个以上的条目时,我不知道如何解决这个问题。值得注意的是,此查询用于SSRS报告,因此我可以使用自定义代码解析数据集并过滤行(使用表可能有助于解决包含两个以上条目的
    项的问题)。但是如果有一个SQL天才在这里提供一个可行的解决方案,那就太好了

    附言:如果有人知道如何修理这张桌子,并能向我解释一下,给他额外的饼干D

    编辑: 这是我目前正在使用的修改后的查询。我会考虑使用@ YyButhHeavter的最新查询,它看起来更健壮。p>
    SELECT * 
      FROM (SELECT ItemID,
                   Item,
                   Priority,
                   Group_,
                   MIN(Priority) OVER
                     ( PARTITION BY item
                     ) AS interItem_MinPriority
              FROM (SELECT ItemID,
                           Item,
                           Priority,
                           Group_,
                           ROW_NUMBER() OVER
                             ( PARTITION BY Item
                                   ORDER BY Priority ASC
                             ) AS interGrp_Rank
                      FROM Test_Table 
                   ) AS TMP
             WHERE interGrp_Rank = 1 -- Exclude all records with the same item/group, but higher priority.
           ) AS TMP2
     WHERE Priority = interItem_MinPriority; -- Exclude which aren't the lowest priority across groups.
    

    没有尝试过,但类似于..选择max(priority)作为mp。。。。。从…起其中组='group1'和mp不在(从…中选择最大优先级)…其中组'group1'


    抱歉在我的手机上打字,不要戴眼镜:)

    如果我正确理解了问题,这应该可以

    SELECT * 
      FROM (SELECT ItemID,
                   Item,
                   Priority,
                   Group_,
                   MIN(Priority) OVER
                     ( PARTITION BY item
                     ) AS interItem_MinPriority
              FROM (SELECT ItemID,
                           Item,
                           Priority,
                           Group_,
                           ROW_NUMBER() OVER
                             ( PARTITION BY Item,
                                            Group_
                                   ORDER BY Priority ASC
                             ) AS interGrp_Rank
                      FROM Test_Table 
                   ) AS TMP
             WHERE interGrp_Rank = 1 -- Exclude all records with the same item/group, but higher priority.
           ) AS TMP2
     WHERE Priority = interItem_MinPriority; -- Exclude which aren't the lowest priority across groups.
    
    我不知道您的SQL Server版本是否支持MIN()OVER()…,但如果不支持,您应该能够很容易地解决这个问题

    编辑:处理领带断裂

    WITH TEST_TABLE (ItemID, Item, Priority, Group_) AS 
     (
     SELECT '16777397','Item 1','5','Group 1' UNION 
     SELECT '16777403','Item 2','5','Group 2' UNION 
     SELECT '16777403','Item 2','10','Group 2' UNION 
     SELECT '16777429','Item 3','1000','Group 3' UNION 
     SELECT '16777430','Item 4','5','Group 1' UNION 
     SELECT '16777454','Item 5','5','Group 4' UNION 
     SELECT '16777455','Item 6','5','Group 5' UNION 
     SELECT '16777459','Item 6','5','Group 6' UNION 
     SELECT '16777468','Item 8','5','Group 7' UNION 
     SELECT '16777479','Item 9','5','Group 4' UNION 
     SELECT '16777481','Item 10','5','Group 4' UNION 
     SELECT '16777496','Item 11','5','Group 6' UNION 
     SELECT '16777514','Item 12','5','Group 4' UNION 
     SELECT '16777518','Item 13','5','Group 8' UNION 
     SELECT '16777518','Item 13','10','Group 8' UNION 
     SELECT '16777518','Item 13','100','Group 1' UNION 
     SELECT '16777520','Item 14','5','Group 9'
     ) 
    
     SELECT ItemID,
            Item,
            Priority,
            Group_
       FROM (SELECT ItemID,
                    Item,
                    Priority,
                    Group_,
                    ROW_NUMBER() OVER
                      ( PARTITION BY item
                            ORDER BY Group_ ASC -- or however you want to break the tie
                      ) AS grp_minPriority_TieBreak
               FROM (SELECT ItemID,
                            Item,
                            Priority,
                            Group_,
                            MIN(Priority) OVER
                              ( PARTITION BY item
                              ) AS interItem_MinPriority
                       FROM (SELECT ItemID,
                                    Item,
                                    Priority,
                                    Group_,
                                    ROW_NUMBER() OVER
                                      ( PARTITION BY Item,
                                                     Group_
                                            ORDER BY Priority ASC
                                      ) AS interGrp_Rank
                               FROM TEST_TABLE 
                            ) AS TMP
                      WHERE interGrp_Rank = 1 -- Exclude all records with the same item/group, but higher priority.
                    ) AS TMP2
              WHERE Priority = interItem_MinPriority -- Exclude which aren't the lowest priority across groups.
           ) AS TMP2
      WHERE grp_minPriority_TieBreak = 1;
    

    如果我了解你的问题

    关于这些标准

  • 如果项目多次出现在同一组中,则只有 应返回具有最低优先级的行。示例:对于项目 2、只返回优先级值为5的行

  • 如果项目出现在组中,但也出现在另一个组中 优先级最低的组,不应显示该组。例子: 选择组1作为过滤器。应显示项目1,但不显示项目 13不应该,因为它也出现在第8组中,具有较低的 优先权(项目13仅出现在第8组中)

  • 我认为我们可以通过使用每个项目的最小优先级而不考虑项目组b来获得正确的结果
    with minPriority as
    (
    select ItemID, Item, Priority , Group_,ROW_NUMBER() over(partition by ItemId order by priority )rn  from Test_table 
    )
    select * from minPriority where rn=1