为GROUP BY创建聚合函数?

时间:2010-09-21 21:20:26

标签: sql sql-server

我有一个查询输出结果如下:

Person   Food
======   ======
Abner    Apple
Beth     Banana
Beth     Peach
Carlos   Grape
Carlos   Kiwi
Carlos   Strawberry
. .      . .

即,它将一个人与一种或多种食物联系起来。我希望聚合函数的功能可以选择食物,但内置的聚合(SUM,MAX,MIN等)都不适用于这种情况。

如果我有一个函数F(),给定食物清单,可以:

  1. 提供有序的食物清单 基于一些优化
  2. 提供最佳的独特选择 从列表中
  3. 有什么方法可以直接将GROUP BY应用到它上面吗?

    有没有人有一个查询示例以其他方式执行此操作,以防这是一个白日梦?

    = = = =

    编辑:让我们说在上面显示的选项中,最佳列表是{Kiwi,Grape,Banana,Strawberry,Apple,Peach},然后输出应该说:

    Abner   Apple
    Beth    Banana
    Carlos  Kiwi
    

    ,即每个人一条记录,每个食物的食物是原始表格中与该人物相关的最佳食物清单中的第一个。

4 个答案:

答案 0 :(得分:2)

SELECT DISTINCT t.Person, f.Food FROM MyTable AS t
CROSS APPLY(
SELECT TOP 1 Food FROM MyTable AS t1 WHERE t.Person = t1.Person
ORDER BY <your method of rating and choosing goes here>
) AS f

答案 1 :(得分:1)

你的意思是,你想连接这些食物吗?

试试这个:

select p.Person, stuff((select ', ' + f.Food [text()] from Food f where f.PersonId = p.Id order by f.Food for xml path('')),1,2,'') [Foods]
from Person p

答案 2 :(得分:1)

请注意,在我的查询中,您可以使用F()行集返回函数替换OptimalFood表(如果我理解正确的话)。

WITH PersonFood (Name, Food) AS (
   SELECT 'Abner', 'Apple'
   UNION ALL SELECT 'Beth', 'Banana'
   UNION ALL SELECT 'Beth', 'Peach'
   UNION ALL SELECT 'Carlos', 'Grape'
   UNION ALL SELECT 'Carlos', 'Kiwi'
   UNION ALL SELECT 'Carlos', 'Strawberry'
   UNION ALL SELECT 'Delilah', 'Passionfruit'
), OptimalFood (Priority, Food) AS (
   SELECT 1, 'Kiwi'
   UNION ALL SELECT 2, 'Grape'
   UNION ALL SELECT 3, 'Banana'
   UNION ALL SELECT 4, 'Strawberry'
   UNION ALL SELECT 5, 'Apple'
   UNION ALL SELECT 6, 'Peach'
), Choices AS (
   SELECT
      Selector = Row_Number() OVER (PARTITION BY F.Name ORDER BY Coalesce(O.Priority, 2147483647)),
      F.Name,
      Food = Coalesce(O.Food, '<None>')
   FROM
      PersonFood F
      LEFT JOIN OptimalFood O ON F.Food = O.Food
)
SELECT
   Name,
   Food
FROM Choices
WHERE Selector = 1;

如果您的桌子上已列出所有人,则可能是更好的方式:

WITH PersonFood (Name, Food) AS (
   SELECT 'Abner', 'Apple'
   UNION ALL SELECT 'Beth', 'Banana'
   UNION ALL SELECT 'Beth', 'Peach'
   UNION ALL SELECT 'Carlos', 'Grape'
   UNION ALL SELECT 'Carlos', 'Kiwi'
   UNION ALL SELECT 'Carlos', 'Strawberry'
   UNION ALL SELECT 'Delilah', 'Passionfruit'
), OptimalFood (Priority, Food) AS (
   SELECT 1, 'Kiwi'
   UNION ALL SELECT 2, 'Grape'
   UNION ALL SELECT 3, 'Banana'
   UNION ALL SELECT 4, 'Strawberry'
   UNION ALL SELECT 5, 'Apple'
   UNION ALL SELECT 6, 'Peach'
), Person AS (
   SELECT DISTINCT Name FROM PersonFood
)
SELECT
   P.Name,
   Food = Coalesce(X.Food, '<None>')
FROM
   Person P
   OUTER APPLY (
      SELECT TOP 1 O.Food
      FROM
         PersonFood F
         INNER JOIN OptimalFood O ON F.Food = O.Food
      WHERE P.Name = F.Name
      ORDER BY O.Priority
   ) X;

我希望在所有这些情况下你实际上使用数字键而不是varchar字符串。我希望希望。 :)

答案 3 :(得分:0)

你可以不用小组去:

SELECT DISTINCT Person, F(Person) AS FoodFunction FROM TableName

您必须更改功能F(),以便它需要人(不是食物清单)并通过以下方式获取食物清单:

SELECT Food FROM TableName
WHERE Person = @Person