简体   繁体   English

为多个列选择不同的值

[英]Selecting distinct values for multiple columns

I have a table where many pieces of data match to one in another column, similar to a tree, and then data at the 'leaf' about each specific leaf 我有一张表,其中许多数据与另一棵树中的另一列相匹配,类似于一棵树,然后在每个特定叶的“叶”处有数据

eg 例如

Food Group      Name       Caloric Value  
Vegetables      Broccoli   100  
Vegetables      Carrots    80    
Fruits          Apples     120  
Fruits          Bananas    120  
Fruits          Oranges    90

I would like to design a query that will return only the distinct values of each column, and then nulls to cover the overflow 我想设计一个查询,该查询将仅返回每列的不同值,然后为null以覆盖溢出

eg 例如

Food group    Name     Caloric Value  
Vegetables    Broccoli 100  
Fruit         Carrots  80  
              Apples   120  
              Bananas  90  
              Oranges   

I'm not sure if this is possible, right now I've been trying to do it with cases, however I was hoping there would be a simpler way 我不确定是否可行,现在我一直在尝试处理案件,但是我希望会有更简单的方法

Seems like you are simply trying to have all the distinct values at hand. 似乎您只是在尝试掌握所有不同的值。 Why? 为什么? For displaying purposes? 出于显示目的? It's the application's job, not the server's. 这是应用程序的工作,而不是服务器的工作。 You could simply have three queries like this: 您可以简单地进行三个查询,如下所示:

SELECT DISTINCT [Food Group] FROM atable;

SELECT DISTINCT Name FROM atable;

SELECT DISTINCT [Caloric Value] FROM atable;

and display their results accordingly. 并相应地显示其结果。

But if you insist on having them all in one table, you might try this: 但是,如果您坚持将它们全部放在一个表中,则可以尝试以下操作:

WITH atable ([Food Group], Name, [Caloric Value]) AS (
  SELECT 'Vegetables', 'Broccoli', 100  UNION ALL
  SELECT 'Vegetables', 'Carrots',  80   UNION ALL
  SELECT 'Fruits',     'Apples',   120  UNION ALL
  SELECT 'Fruits',     'Bananas',  120  UNION ALL
  SELECT 'Fruits',     'Oranges',  90   
),
atable_numbered AS (
  SELECT
    [Food Group], Name, [Caloric Value],
    fg_rank = DENSE_RANK() OVER (ORDER BY [Food Group]),
    n_rank  = DENSE_RANK() OVER (ORDER BY Name),
    cv_rank = DENSE_RANK() OVER (ORDER BY [Caloric Value])
  FROM atable
)
SELECT
  fg.[Food Group],
  n.Name,
  cv.[Caloric Value]
FROM (
  SELECT fg_rank FROM atable_numbered  UNION
  SELECT n_rank  FROM atable_numbered  UNION
  SELECT cv_rank FROM atable_numbered
) r (rank)
  LEFT JOIN (
    SELECT DISTINCT [Food Group], fg_rank
    FROM atable_numbered) fg ON r.rank = fg.fg_rank
  LEFT JOIN (
    SELECT DISTINCT Name, n_rank
    FROM atable_numbered) n  ON r.rank = n.n_rank
  LEFT JOIN (
    SELECT DISTINCT [Caloric Value], cv_rank
    FROM atable_numbered) cv ON r.rank = cv.cv_rank
ORDER BY r.rank

I guess what I would want to know is why you need this in one result set? 我想我想知道的是为什么您需要一个结果集呢? What does the code look like that would consume this result? 代码看起来像什么将消耗此结果? The attributes on each row have nothing to do with each other. 每行上的属性彼此无关。 If you want to, say, build the contents of a set of drop-down boxes, you're better off doing these one at a time. 例如,如果要构建一组下拉框的内容,则最好一次执行一次。 In your requested result set, you'd need to iterate through the dataset three times to do anything useful, and you would need to either check for NULL each time or needlessly iterate all the way to the end of the dataset. 在您请求的结果集中,您需要遍历数据集三次以执行任何有用的操作,并且您需要每次都检查NULL或不必要地迭代直到数据集的末尾。

If this is in a stored procedure, couldn't you run three separate SELECT DISTINCT and return the values as three results. 如果这是在存储过程中,则无法运行三个单独的SELECT DISTINCT并将值作为三个结果返回。 Then you can consume them one at a time, which is what you would be doing anyway I would guess. 然后,您一次可以食用一次,我想您无论如何都会这样做。

If there REALLY IS a connection between the values, you could add each of the results to an array or list, then access all three lists in parallel using the index. 如果值之间确实存在联系,则可以将每个结果添加到数组或列表中,然后使用索引并行访问所有三个列表。

Something like this maybe? 像这样的东西?

select *
from (
  select case 
          when row_number() over (partition by fruit_group) = 1 then fruit_group
          else null 
        end as fruit_group,
        case 
          when row_number() over (partition by name) = 1 then name
          else null
        end as name,
        case 
          when row_number() over (partition by caloric) = 1 then caloric
          else null
        end as caloric
  from your_table
) t
where fruit_group is not null
   or name is not null
   or caloric is not null

But I fail to see any sense in this 但我看不出这有什么意义

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM