【问题标题】:How to insert a row in mysql before union?如何在联合之前在mysql中插入一行?
【发布时间】:2013-02-06 05:33:11
【问题描述】:

假设我有以下内容:

CREATE TABLE newtable AS (
SELECT @rownum:=@rownum+1 as rownum, name, age FROM (
    SELECT name, age FROM clubAmembers
    UNION
    SELECT name, age FROM clubBmembers
)
) AS atable

我怎样才能使我可以在 SELECT 联合之前“在表的开头插入新行”,以便它以:

rownum | name| age
1 | "Jordan" | 6  <-- This is an arbitrarily inserted record with name="Jordan" age="6" that is not a part of any of the clubAmembers or clubBmembers table.

表格的其余部分(第 2 行及以后)将包含与 clubAmembers 然后 clubBmembers 的联合的实际结果。

基本上我正在寻找: 创建表 插入一行“乔丹”| 6 使用 union 执行 select,使得第一行之后的行以 "rownum=2" 开头,所有来自 clubAmembers 的数据等。

如何最好地做到这一点?

【问题讨论】:

  • 订单只能通过 ORDER BY 子句可靠地建立。这是因为大多数 SQL,包括 UNION,都是“基于集合的”。
  • 如果我只是联合 clubAmembers 和 clubBmembers,则 SELECT @rownum:=@rownum+1 建立顺序(如编号 1 到 ... n 的成员数)。如果我不可能在这些表合并之前插入一行,同时保留 rownum 的顺序,那么完成我想要的最好的选择是什么?
  • 它不建立由 inside 联合产生的元素的顺序:选择操作发生在后面。它可能会按预期工作。或者它可能不会。

标签: mysql sql


【解决方案1】:

“在表的开头”对关系数据库没有真正意义,因为在您使用ORDER BY 子句之前,无法保证返回的顺序结果,此时磁盘上的顺序无论如何都会成为一个有争议的问题。

在您的情况下,由于您想保证结果子句中的顺序(因此订购@rownum,您将不得不使用ORDER BY。类似:

CREATE TABLE newtable AS (
    SELECT @rownum:=@rownum+1 as rownum, name, age 
    FROM (
        SELECT 'Jordan' AS name, 6 AS age, 0 AS ord
        UNION
        SELECT name, age, 1 AS ord FROM clubAmembers
        UNION
        SELECT name, age, 1 AS ord FROM clubBmembers
        ORDER BY ord
    )
) AS atable

请注意,这绝不保证clubAmembers 中的行的rownumclubBmembers 中的行低。如果要保证clubAmembers 具有较低的rownum,同时保持UNION 的语义(相对于UNION ALL),可以使用以下内容:

CREATE TABLE newtable AS (
    SELECT @rownum:=@rownum+1 as rownum, name, age 
    FROM (
        SELECT 'Jordan' AS name, 6 AS age, 0 AS ord
        UNION ALL
        SELECT name, age, 1 AS ord FROM clubAmembers
        UNION ALL
        SELECT name, age, 2 AS ord FROM clubBmembers AS b
        WHERE NOT EXISTS(SELECT 1 FROM clubAmembers AS a 
                         WHERE a.name = b.name AND a.age = b.age)
        ORDER BY ord
    )
) AS atable

请注意,如果 {name, age} 可以在 clubXmembers 表中重复,则需要添加 DISTINCT

...
SELECT DISTINCT name, age, 1 AS ord FROM clubAmembers
UNION ALL
...

根据 cmets 中的请求,如果您有一个 clubCmembers 表,您会这样做:

CREATE TABLE newtable AS (
    SELECT @rownum:=@rownum+1 as rownum, name, age 
    FROM (
        SELECT 'Jordan' AS name, 6 AS age, 0 AS ord
        UNION ALL
        SELECT name, age, 1 AS ord FROM clubAmembers
        UNION ALL
        SELECT name, age, 2 AS ord FROM clubBmembers AS b
        WHERE NOT EXISTS(SELECT 1 FROM clubAmembers AS a 
                         WHERE a.name = b.name AND a.age = b.age)
        SELECT name, age, 3 AS ord FROM clubCmembers AS c
        WHERE NOT EXISTS(SELECT 1 FROM clubAmembers AS a 
                         WHERE a.name = c.name AND a.age = c.age)
        AND NOT EXISTS(SELECT 1 FROM clubBmembers AS b
                       WHERE b.name = c.name AND b.age = c.age)
        ORDER BY ord
    )
) AS atable

【讨论】:

  • ord的目的是什么?这是否意味着如果我将 clubBmembers 上的 SELECT 的 ord 设置为“2”,我可以保证 clubAmembers 中的行的 rownum 低于 clubBmembers 中的行?
  • @SeiSeiei ord 建立一个顺序,即您的“Jordan”行排在第一位 (ord = 0)。如果想让clubAmembers排在前面,可以为clubBmembers设置ord为2,但是UNION的含义(相对于UNION ALL会丢失。我会编辑解释一下。
  • 我没有得到完整的订购信息。如果您根本不订购,所有东西都将以相同的顺序插入。没有?
  • @user1988148 对于UNION ALL,那应该是真的,是的(尽管我什至不知道这是 100%)。但是UNION 是一个删除重复项的集合操作,因此确实不能保证返回结果的顺序。
  • 因此,除非您执行额外的 WHERE NOT EXISTS 检查,否则为“ord”设置不同的值会破坏 UNION。如果有“clubCmembers”,您是否可以修改示例以包含一个潜在的案例,以便我可以确保我得到它?另外,假设 clubBmembers 本身可能有重复的姓名/年龄,但相同的姓名/年龄对不会出现在 clubAmembers 或 clubCmembers 中,是否仍然需要使用“WHERE NOT EXISTS”子句?
【解决方案2】:

我不确定我是否做对了。但是你为什么不像这样添加另一个联合:

CREATE TABLE newtable AS (
SELECT @rownum:=@rownum+1 as rownum, name, age FROM (
    SELECT 1, "Jordan", 6
    UNION ALL
    SELECT name, age FROM clubAmembers
    UNION ALL
    SELECT name, age FROM clubBmembers
)
) AS atable

【讨论】:

  • 我认为 OP 想在新表的第一个位置插入提到的记录(带有 Jordan 的记录),然后从子查询中放入其余记录。
  • 我认为我写的查询会产生和你一样的结果。你不觉得吗?
  • 你的权利,对不起,我没有看到第一条记录的行。 +1
【解决方案3】:

您可以将创建表状态与插入状态分开:

  1. 创建表(你必须知道哪些列会在那里)
  2. 插入您的第一条记录(INSERT INTO .... Values(...))
  3. 使用您的语句,但使用 insert into 而不是创建表,例如:INSERT INTO YourNewTable.... Values(YourSubQuery)(列的 Nr 和 tye 必须与您的子查询匹配)

【讨论】:

  • 请示例查询。如果可能,想知道性能/速度与其他解决方案(即 ORDER BY)的比较
【解决方案4】:

我相信应该这样做:

CREATE TABLE newtable AS (
  SELECT (@rownum:=IFNULL(@rownum,0)+1)+1 as rownum, name, age FROM (
    SELECT name, age FROM clubAmembers
    UNION
    SELECT name, age FROM clubBmembers
  ) AS s
  UNION ALL
  SELECT 1, 'Jordan', 6
) AS atable

SQL Fiddle 演示:http://sqlfiddle.com/#!2/ab825/6

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多