MySQL内部联接更改记录的顺序

时间:2015-10-23 07:59:28

标签: mysql sql join

我有一个表 Table1 ,其中包含5列这样的

|   ID   |   Name  |   V1   |   V2   |   V3   |
|   1    |    A    |   103  |   507  |   603  |
|   2    |    B    |   514  |   415  |   117  |

和另一个表 Table2 ,其值如下

|  Values |  Rooms  |
|   103   |   ABC   |
|   507   |   DEF   |
|   603   |   GHI   |
|   514   |   JKL   |
|   415   |   MNO   |
|   117   |   PQR   |

我正在运行联接查询,以便将 Table1 加入 Table1 作为

的房间
SELECT t2.values, t2.rooms, t1.Name FROM Table2 t2
INNER JOIN Table1 t1 ON t1.V1 = t2.Values
                    OR t1.V2 = t2.Values
                    OR t1.V3 = t2.Values;

此查询获取结果,但按t2.values的升序排列。我不想改变任何订单。我只是希望得到 Table1 具有值的结果。

|  Values |  Rooms  |  Names  |
|   103   |   ABC   |    A    |
|   117   |   PQR   |    B    |
|   415   |   MNO   |    B    |
|   507   |   DEF   |    A    |
|   514   |   JKL   |    B    |
|   603   |   GHI   |    A    |

上述结果根据T2.Values排序,这些值来自t1.V1,t1.V2,T1.V3。我不想要订单结果。我希望结果符合t1.V1,t1.V2,T1.V3值。如果我们看到 Table1 ,则值为103,507,603,514,415,117,因此结果应为

|  Values |  Rooms  |  Names  |
|   103   |   ABC   |    A    |
|   507   |   DEF   |    A    |
|   603   |   GHI   |    A    |
|   415   |   MNO   |    B    |
|   514   |   JKL   |    B    |
|   117   |   PQR   |    B    |

我希望我能以某种方式更好地解释。如果它仍然不清楚,请允许我进行更多编辑。

正如 paxdiablo 建议的那样,我尝试添加ORDER BY t1.name,但这不是排序,结果是相同的。为什么呢?

3 个答案:

答案 0 :(得分:4)

  

我只想获得Table1具有值的结果。

这是你犯错误的地方。 Table1,至少就SQL而言,没有订单。表是提取数据时强加顺序的无序集合(如果您愿意)。

除非您专门使用selectorder by,否则SQL group by语句绝对保证返回结果的顺序。即使select * from table1也可以按照DBMS认为适合的顺序返回行。

如果您需要特定订购,则需要明确要求。例如,如果您希望按房间名称排序,请在查询结束时重新order by t1.name。虽然我可能会使用order by t1.name, t2.rooms来完成整个生猪并使用辅助排序顺序。

或者,要对值进行排序,请添加order by t2.values

例如,将此架构/数据打入SQLFiddle

create table table1(
    id    integer,
    name  varchar(10),
    v1    integer,
    v2    integer,
    v3    integer);
insert into table1 (id,name,v1,v2,v3) values (1,'a',103,507,603);
insert into table1 (id,name,v1,v2,v3) values (2,'b',514,415,117);

create table table2 (
    val   integer,
    room  varchar(10));
insert into table2(val,room) values (103,'abc');
insert into table2(val,room) values (507,'def');
insert into table2(val,room) values (603,'ghi');
insert into table2(val,room) values (514,'jkl');
insert into table2(val,room) values (415,'mno');
insert into table2(val,room) values (117,'pqr');

然后执行:

select t2.val, t2.room, t1.name from table2 t2
inner join table1 t1 on t1.v1 = t2.val
                     or t1.v2 = t2.val
                     or t1.v3 = t2.val

给我们一个任意的排序(它可能看起来喜欢roomsname内的排序,但不保证这样做:

| val | room | name |
|-----|------|------|
| 103 |  abc |    a |
| 507 |  def |    a |
| 603 |  ghi |    a |
| 514 |  jkl |    b |
| 415 |  mno |    b |
| 117 |  pqr |    b |

当我们更改它以对两个降序键order by t1.name desc, t2.room desc进行排序时,我们可以看到它基于此重新排序:

| val | room | name |
|-----|------|------|
| 117 |  pqr |    b |
| 415 |  mno |    b |
| 514 |  jkl |    b |
| 603 |  ghi |    a |
| 507 |  def |    a |
| 103 |  abc |    a |

最后,将排序条款更改为order by t2.val asc,我们按值顺序得到它:

| val | room | name |
|-----|------|------|
| 103 |  abc |    a |
| 117 |  pqr |    b |
| 415 |  mno |    b |
| 507 |  def |    a |
| 514 |  jkl |    b |
| 603 |  ghi |    a |

最后,如果您打算按table1每行中的列顺序对其进行排序(因此订单从左到右v1v2,{{1}您可以引入一个人工排序键,可以使用v3语句根据匹配的列进行选择,也可以运行多个查询,这些查询可能更有效:

  • 你没有执行每行功能,这些功能往往不能很好地扩展;和
  • 在较大的DBMS中,它们可以并行化。

多重查询选项类似于:

case

并生成:

select 1 as minor, t2.val as val, t2.room as room, t1.name as name from table2 t2
    inner join table1 t1 on t1.v1 = t2.val
union all select 2 as minor, t2.val as val, t2.room as room, t1.name as name from table2 t2
    inner join table1 t1 on t1.v2 = t2.val
union all select 3 as minor, t2.val as val, t2.room as room, t1.name as name from table2 t2
    inner join table1 t1 on t1.v3 = t2.val
order by name, minor

你可以看到它使用| minor | val | room | name | |-------|-----|------|------| | 1 | 103 | abc | a | | 2 | 507 | def | a | | 3 | 603 | ghi | a | | 1 | 514 | jkl | b | | 2 | 415 | mno | b | | 3 | 117 | pqr | b | 作为主键,并将行中值的位置作为次要键。

现在有些人可能认为引入假列进行排序是一种丑陋的方法,但它是一种经过验证的方法,可以提高性能。但是,你不应该相信我(或任何人)。我的优化主要咒语是 measure,不要猜测。

答案 1 :(得分:2)

我知道你已经接受了答案,但我觉得你希望他们按照table1中ID的顺序排序,然后按照你的排序(v1,v2,v3)排序;匹配。在这种情况下,这样的事情应该有效:

SELECT t2.`values`, t2.rooms, t1.Name FROM Table2 t2
INNER JOIN Table1 t1 ON t1.V1 = t2.`values`
                    OR t1.V2 = t2.`values`
                    OR t1.V3 = t2.`values`
ORDER BY
    t1.id,
    CASE 
        WHEN t1.v1 = t2.`values` THEN 1
        WHEN t1.v2 = t2.`values` THEN 2
        WHEN t1.V3 = t2.`values` THEN 3
    END

(注意我引用values,因为它是SQL中的关键字...)

我在这里做的是:

首先,我按t1.id排序,根据t1表格中的行为您提供粗略的排序顺序。

然后,我使用CASE语句根据结果行中匹配的Values列添加辅助排序。对于查询结果的每一行,如果结果是由t1.v1t2.values之间的匹配生成的,则CASE语句的计算结果为1.如果结果是由于{{1}之间的匹配}和t1.v2,然后我们得到2.如果结果是由于t2.valuest1.v3之间的匹配,那么我们得到3.

因此整体排序顺序首先取决于t2.values中行的顺序,然后是t1t1之间匹配的列的顺序。排在你的结果中,这似乎是要求(虽然很难用语言表达!)

答案 2 :(得分:0)

该查询正在使用按升序排列的值对表进行排序 - 例如" 103< 117< 415等等......"但是你希望他们采取在实际表中排序的顺序,即" 103而不是507而不是603,依此类推"它按照插入的方式排序,你只想保留这个排序顺序。你可以实现的一种可能的方法是在第二个表中使用一个额外的时间戳字段,它可以跟踪插入时间,因此你可以使用那个时间戳就像"订购时间戳"在你的查询..