【问题标题】:order by after full outer join完全外连接后排序
【发布时间】:2013-12-18 15:03:12
【问题描述】:

我以PostgreSQL 9.3.1 模式在http://sqlfiddle.com 上创建下表:

CREATE TABLE t
(
  id serial primary key,
  m varchar(1),
  d varchar(1),
  c int
);

INSERT INTO t
(m, d, c)
VALUES
('A', '1', 101),
('A', '2', 102),
('A', '3', 103),
('B', '1', 104),
('B', '3', 105);

表:

| ID | M | D |   C |
|----|---|---|-----|
|  1 | A | 1 | 101 |
|  2 | A | 2 | 102 |
|  3 | A | 3 | 103 |
|  4 | B | 1 | 104 |
|  5 | B | 3 | 105 |

由此我想生成这样一张表:

| M | D |     ID |      C |
|---|---|--------|--------|
| A | 1 |      1 |    101 |
| A | 2 |      2 |    102 |
| A | 3 |      3 |    103 |
| B | 1 |      4 |    104 |
| B | 2 | (null) | (null) |
| B | 3 |      5 |    105 |

但以我目前的说法

select * from
  (select * from
    (select distinct m from t) as dummy1,
    (select distinct d from t) as dummy2) as combi
  full outer join
    t
  on combi.d = t.d and combi.m = t.m

我只得到以下内容

| M | D |     ID |      C |
|---|---|--------|--------|
| A | 1 |      1 |    101 |
| B | 1 |      4 |    104 |
| A | 2 |      2 |    102 |
| A | 3 |      3 |    103 |
| B | 3 |      5 |    105 |
| B | 2 | (null) | (null) |

到目前为止,尝试按 m,d 排序失败:

select * from
  (select * from
    (select * from
      (select * from
        (select distinct m from t) as dummy1,
        (select distinct d from t) as dummy2) as kombi
      full outer join
        t
      on kombi.d = t.d and kombi.m = t.m) as result)
order by result.m

错误信息:

ERROR: subquery in FROM must have an alias: select * from (select * from (select * from (select * from (select distinct m from t) as dummy1, (select distinct d from t) as dummy2) as kombi full outer join t on kombi.d = t.d and kombi.m = t.m) as result) order by result.m

如果有人可以向我指出我做错了什么并可能显示正确的陈述,那就太酷了。

【问题讨论】:

  • 你能详细说明你想要完成什么吗?

标签: sql postgresql sqlfiddle


【解决方案1】:
select * from
  (select kombi.m, kombi.d, t.id, t.c from
    (select * from
      (select distinct m from t) as dummy1,
      (select distinct d from t) as dummy2) as kombi
     full outer join t
  on kombi.d = t.d and kombi.m = t.m) as result
order by result.m, result.d

【讨论】:

    【解决方案2】:

    我认为你的问题是顺序。您可以使用 order by 子句解决此问题:

    select * from
      (select * from
        (select distinct m from t) as dummy1,
        (select distinct d from t) as dummy2) as combi
      full outer join
        t
      on combi.d = t.d and combi.m = t.m
    order by combi.m, combi.d
    

    您需要指定要订购的数据。在这种情况下,您从组合表中取回该行,因此您需要这么说。 http://sqlfiddle.com/#!15/ddc0e/17

    【讨论】:

      【解决方案3】:

      您也可以使用列号而不是名称来进行排序。

      select * from
        (select * from
          (select distinct m from t) as dummy1,
          (select distinct d from t) as dummy2) as combi
        full outer join
          t
        on combi.d = t.d and combi.m = t.m
      order by 1,2;
      
      | M | D |     ID |      C |
      |---|---|--------|--------|
      | A | 1 |      1 |    101 |
      | A | 2 |      2 |    102 |
      | A | 3 |      3 |    103 |
      | B | 1 |      4 |    104 |
      | B | 2 | (null) | (null) |
      | B | 3 |      5 |    105 |
      

      【讨论】:

        【解决方案4】:

        你只需要一个数据透视表

        查询很简单

        select classes.M, p.i as D, t.ID, t.C
        from (select M, max(D) MaxValue from t group by m) classes
        inner join pivot p
        on p.i =< classes.MaxValue
        left join t
        on t.M = classes.M
        and t.D = p.i
        

        数据透视表在某种程度上是一个虚拟表

        CREATE TABLE Pivot (
         i INT,
         PRIMARY KEY(i)
        )
        

        填充是某种方式

        CREATE TABLE Foo(
        i CHAR(1)
        )
        
        INSERT INTO Foo VALUES('0')
        INSERT INTO Foo VALUES('1')
        INSERT INTO Foo VALUES('2')
        INSERT INTO Foo VALUES('3')
        INSERT INTO Foo VALUES('4')
        INSERT INTO Foo VALUES('5')
        INSERT INTO Foo VALUES('6')
        INSERT INTO Foo VALUES('7')
        INSERT INTO Foo VALUES('8')
        INSERT INTO Foo VALUES('9')
        

        使用 Foo 表中的 10 行,您可以轻松地用 1,000 行填充数据透视表。要从 10 行中获取 1000 行,请将 Foo 与自身连接 3 次以创建笛卡尔积:

        INSERT INTO Pivot
        SELECT f1.i+f2.i+f3.i
        FROM Foo f1, Foo F2, Foo f3
        

        您可以在 Ales Spetic 的 Jonathan Gennick 撰写的 Transac-SQL Cookbook 中阅读相关内容

        【讨论】:

          【解决方案5】:

          您只需要按最终列定义进行排序。 t.mt.d。所以你的最终 SQL 将是......

          SELECT * 
          FROM   (SELECT * 
                  FROM   (SELECT DISTINCT m FROM   t) AS dummy1, 
                         (SELECT DISTINCT d FROM   t) AS dummy2) AS combi 
                 FULL OUTER JOIN t 
                              ON combi.d = t.d 
                                 AND combi.m = t.m 
          ORDER  BY t.m, 
                    t.d; 
          

          同样从查询优化的角度来看,现在最好有多层子查询。

          【讨论】:

            【解决方案6】:

            我认为您需要另一个相关名称 - dummy3? - 在 'as result )' 之后,在 order by 之前。

            【讨论】:

              猜你喜欢
              • 2012-01-06
              • 2013-03-11
              • 1970-01-01
              • 1970-01-01
              • 2021-10-12
              • 1970-01-01
              • 2014-09-23
              • 2017-06-10
              相关资源
              最近更新 更多