SQL分组聚合为不同的值

时间:2009-02-12 21:43:04

标签: sql sql-server outer-join

我有一个类似于:

的数据库表

ForeignId: int
Key: varchar
Value: varchar

其中ForeignId和Key构成唯一主键

我可以使用

轻松确定为给定文档集定义的密钥集

SELECT DISTINCT [Key] FROM [Table] WHERE [ForeignId] IN (...)

然而,我想要做的是进一步区分每个属性的每个值的值,在每个ForeignId相同的情况下(在值不同的情况下为NULL或其他一些sentinal值)

如果我这样做:

ForeignId  Key  Value
1            1      A
1            2      B
1            3      C
2            1      A
2            2      Z
3            1      A
3            2      Z

我希望输出如下:

Key   Value
1     A      -- All 3 are the same
2     NULL   -- More than one distinct value (B, and Z)
3     NULL   -- Defined for only one ForeignId

我能想到的最好的是


SELECT [Key], MAX([Value]), MIN([Value]) FROM [Table]
WHERE [ForeignId] IN (...)
GROUP BY [Key]

并查找返回的max和min值不同的任何实例。如果它们是相同的,我假设所有的值都匹配,如果它们不同,我知道有不止一个不同的值。

这里缺少的是第3部分,如果任何单个项目根本没有定义,我需要将值标记为不同。在上面的例子中,我的当前代码将返回键3的值C,即使它没有为某些ForeignIds定义。

3 个答案:

答案 0 :(得分:1)

好的 - 如果我理解你的问题,你需要生成一个包含两列,键和值的列表。

每个键的列表都有一行,value列可以定义为:

如果未为所有ForeignID定义,则为NULL 如果为所有键定义但包含多个值,则为NULL 如果为所有键定义的值,该值始终相同?

所以,我认为我们想做这样的事情:

SELECT
    TABLE.KEY,
    data.VAL
FROM
    TABLE
LEFT JOIN
(
   SELECT KEY, VALUE FROM TABLE GROUP BY KEY, VALUE HAVING COUNT(*) = x
) data


其中x是不同键的数量(您可能希望将其放入子查询中)。

左连接将确保列出所有键,子查询将仅在分组计数等于键数时返回值。

我无法访问sql(我在家,新PC)来测试我的语法,但我认为这个想法可以让你走上正确的道路。

如果我误解了您的问题,请告诉我

答案 1 :(得分:0)

我不认为你可以不使用某种代码(存储过程可以工作)而不用它真的很难看(并且很可能很慢)。

这是我最好的尝试。这很难看。我不想在生产中使用它。我质疑它的表现如何(时间明智)。这是MySQL的说法,因为这就是我所熟悉的

SELECT key, IF(EXISTS (SELECT 1 FROM table t
                        WHERE t.key = key AND t.value != value),
               null, value)
FROM table
GROUP BY key
ORDER BY key

以下是各部分的解释:

SELECT 1 FROM table t WHERE t.key = key AND t.value != value

如果表中的另一行具有相同的键但值不同,则返回一行。

IF检查上面的查询是否返回了一行。如果它(EXISTS工作)然后返回null(因为有一个具有不同值的行)。如果它没有返回一行,那么它们都匹配,我们返回值。

GROUP BY确保每个键只执行一次。

ORDER BY让它漂亮。

答案 2 :(得分:0)

克里斯非常喜欢它。添加另一个组,你就是金色。

SELECT
    TABLE.KEY,
    data.VAL
FROM
    TABLE
LEFT JOIN
(
   SELECT KEY, VALUE FROM TABLE GROUP BY KEY, VALUE HAVING COUNT(*) = x
) data on Table.Key = data.Key
group by Table.Key, data.VAL