sql group by one column,然后在一列上过滤并为不同的值创建新列

时间:2013-04-05 16:52:22

标签: sql ms-access ms-access-2007 pivot

在MS Access查询中,如何对一列进行分组,然后使用max ID从表中获取特定值。我知道我可以分组并使用max来获取最大ID但不知道如何获得多个最大ID。

如果我有这样的表:

+----+------+-------+------+
| ID | Col1 | Col2  | Col3 |
+----+------+-------+------+
|  1 | a    | one   |  100 |
|  2 | a    | two   |  200 |
|  3 | a    | three |  300 |
|  4 | a    | four  |  400 |
|  5 | a    | five  |  500 |
|  6 | b    | one   |  600 |
|  7 | b    | two   |  700 |
|  8 | b    | three |  800 |
|  9 | b    | four  |  900 |
| 10 | b    | one   | 1000 |
| 11 | b    | three | 1100 |
| 12 | b    | six   | 1200 |
| 13 | c    | one   | 1300 |
| 14 | c    | two   | 1400 |
| 15 | c    | three | 1500 |
| 16 | c    | four  | 1600 |
| 17 | c    | six   | 1700 |
| 18 | c    | three | 1800 |
| 19 | c    | two   | 1900 |
| 20 | c    | one   | 2000 |
+----+------+-------+------+

我希望得到这个:

+------+------+------+-------+
| Col1 | one  | two  | three |
+------+------+------+-------+
| a    |  100 |  200 |   300 |
| b    | 1000 |  700 |  1100 |
| c    | 2000 | 1900 |  1800 |
+------+------+------+-------+

当Col1 = b,Col2 = 1时,ID = 6和10.由于10更大,因此得到该行的值为1000.表的其余部分相同...

我不能为我的生活弄清楚如何做到这一点。

6 个答案:

答案 0 :(得分:1)

这将返回您在Access 2007中使用示例数据请求的结果。

SELECT
    sub.Col1,
    DLookup('Col3', 'YourTable', 'ID=' & sub.MaxOfID1) AS [one],
    DLookup('Col3', 'YourTable', 'ID=' & sub.MaxOfID2) AS [two],
    DLookup('Col3', 'YourTable', 'ID=' & sub.MaxOfID3) AS [three]
FROM
    (
        SELECT
            y.Col1,
            Max(IIf(y.Col2='one', y.ID, 0)) AS MaxOfID1,
            Max(IIf(y.Col2='two', y.ID, 0)) AS MaxOfID2,
            Max(IIf(y.Col2='three', y.ID, 0)) AS MaxOfID3
        FROM YourTable AS y
        GROUP BY y.Col1
    ) AS sub;

答案 1 :(得分:0)

由于您尚未提及您的RDBMS,因此几乎所有RDBMS都支持以下查询。

SELECT  Col1,
        MAX(CASE WHEN Col2 = 'one' THEN Col3 END) one,
        MAX(CASE WHEN Col2 = 'two' THEN Col3 END) two,
        MAX(CASE WHEN Col2 = 'three' THEN Col3 END) three
FROM    TableName
GROUP   BY Col1

输出

╔══════╦══════╦══════╦═══════╗
║ COL1 ║ ONE  ║ TWO  ║ THREE ║
╠══════╬══════╬══════╬═══════╣
║ a    ║  100 ║  200 ║   300 ║
║ b    ║ 1000 ║  700 ║  1100 ║
║ c    ║ 2000 ║ 1900 ║  1800 ║
╚══════╩══════╩══════╩═══════╝

答案 2 :(得分:0)

select col1, 
    max(case col2 when 'one' then col3 else 0 end) as One,
    max(case col2 when 'two' then col3 else 0 end) as Two,
    max(case col2 when 'three' then col3 else 0 end) as three
from MyTable
group by col1

答案 3 :(得分:0)

这适用于MS-Access:

TRANSFORM Max(tbl.Col3) AS MaxDiCol3
SELECT tbl.Col1
FROM tbl
WHERE (((tbl.Col2)="one" Or (tbl.Col2)="two" Or (tbl.Col2)="three"))
GROUP BY tbl.Col1
PIVOT tbl.Col2;

如果你需要获得最大ID而不是最大值,我建议你改用它:

TRANSFORM Max(tbl.ID) AS MaxDiCol3
SELECT tbl.Col1
FROM tbl
WHERE (((tbl.Col2)="one" Or (tbl.Col2)="two" Or (tbl.Col2)="three"))
GROUP BY tbl.Col1
PIVOT tbl.Col2;

并将其另存为查询,例如Query1。然后,您可以使用以下方法获取实际值:

SELECT
  Query1.Col1,
  tbl.Col3 AS one,
  tbl_1.Col3 AS two,
  tbl_2.Col3 AS three
FROM
  ((Query1 LEFT JOIN tbl ON Query1.one = tbl.ID)
  LEFT JOIN tbl AS tbl_1 ON Query1.two = tbl_1.ID)
  LEFT JOIN tbl AS tbl_2 ON Query1.three = tbl_2.ID;

答案 4 :(得分:-1)

试试这个:

SELECT 
  t1. col1, 
  MAX(CASE WHEN t1.col2 = 'one' THEN t1.col3 END) AS 'one',
  MAX(CASE WHEN t1.col2 = 'two' THEN t1.col3 END) AS 'two',
  MAX(CASE WHEN t1.col2 = 'three' THEN t1.col3 END) AS 'three'
FROM tablename AS t1
INNER JOIN
(
  SELECT col1, MAX(ID) AS MAXID
  FROM tablename
  WHERE col2 IN('one', 'two', 'three')
  GROUP BY col1, col2
) AS t2 ON t1.col1 = t2.col1 AND t1.id = t2.maxid
GROUP BY t1.col1;

带有子查询的JOIN只会为您提供每个col1col2的最大ID值。

SQL Fiddle Demo

这会给你:

| COL1 |  ONE |  TWO | THREE |
------------------------------
|    a |  100 |  200 |   300 |
|    b | 1000 |  700 |  1100 |
|    c | 2000 | 1900 |  1800 |

<击>

<击>

但是:如果您使用支持窗口函数的RDBMS和PIVOT表运算符(如SQL Server),则可以执行以下操作:

WITH CTE 
AS
(
  SELECT *,
    ROW_NUMBER() OVER(PARTITION BY col1, col2
                      ORDER BY ID) AS RN
  FROM tablename
  WHERE col2 IN('one', 'two', 'three')
)
SELECT *
FROM
(
  SELECT col1, col2, col3
  FROM CTE
  WHERE RN <= 3
) AS t
PIVOT
(
  MAX(col3)
  FOR col2 IN([one], [two], [three])
) AS p;

Updated SQL Fiddle Demo

<击>

答案 5 :(得分:-1)

我认为你需要 Dynamic PIVOT and Group By

SQL FIDDLE DEMO


declare @cols varchar(max)
declare @query varchar(max)
DECLARE @selective nvarchar(max)

SELECT @selective =
  STUFF((SELECT ',MAX(' + QUOTENAME(t.col2) +') as ' + QUOTENAME(t.col2)  AS ColName    
         from (
         select distinct  col2                            
         FROM yourtable
         )  t                     
         FOR XML PATH( ''), TYPE).value ('.', 'nvarchar(max)'),1,1,'')

select @cols = STUFF((SELECT ',' + QUOTENAME(t.col2)  AS ColName   
         from (
         select distinct  col2                            
         FROM yourtable
         )  t                 
         FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'),1,1,'')

set @query = ' ;with CTE_PivotTable
               as
               (
               select ID, Col1, ' + @cols + 
             ' from 
                    ( select ID, Col1, Col2, Col3 
                      from yourtable
                    ) t
                    pivot
                       (
                          max(col3) for col2 in ('+@Cols+')
                        ) as P
                )
                select Col1, ' + @selective + 
                'from CTE_PivotTable
                 group by Col1'

exec(@query)    

输出结果



COL1 | FIVE  |  FOUR  |  ONE  |  SIX  |  THREE  | TWO
-----------------------------------------------------
a    | 500   |  400   |  100  | (null)|  300    | 200 
b    | (null)|  900   |  1000 | 1200  |  1100   | 700 
c    |(null) |  1600  |  2000 | 1700  |  1800   |1900