【问题标题】:SQL insert into using WITH statement throws an unexpected 'insert' error使用 WITH 语句插入 SQL 会引发意外的“插入”错误
【发布时间】:2019-06-26 14:23:31
【问题描述】:

作为我的 SQL 查询的一部分,我首先根据特定条件创建一个名为“新”的表,然后根据特定条件创建 insert intonew 表中来自不同表 old 的一些列。这是我正在尝试做的简化版本:

   item    | subitem    |   stage    |   id     | 
    -----------------------------------------------
    i1      | s1         |  picked    |    1     |
    i1      | s2         |  shipped   |    1     |
    i2      | s4         |  picked    |    2     |
    i3      | s10        | shipped    |    2     |
    i3      | s11        | eligible   |    0     |
    i4      | s2         |not eligible|    0     |
    i1      | s1         |  picked    |    3     |
    i1      | s2         |  picked    |    3     |

我希望输出如下:

    item1|subitem1|item2|subitem2|pair_volume|item1pick|item1ship|item2pick|item2ship|
-------------------------------------------------------------------------------------
    i1   |   s1   |  i1 | s2     | 2         |  2      | 0       | 2       | 1       |
    i1   | s1     | i2  | s4     | 1         |1        | 0       | 1       | 1       |  
    ....
    .....
    ....

基本上,我在这里要做的是:

我想首先将item, subitem 与自身进行交叉连接,因此我拥有item1subitem1item2subitem2 的所有可能组合。

以下是阶段的定义方式。如果一个阶段是合格的,那么它就是合格的,而如果一个阶段被选中,则意味着该项目既符合条件又被选中。如果某个阶段已发货,则意味着该项目符合条件、已挑选并已发货。只提到了最后一个阶段。

现在,对于每个item1, subitem1 - item2, subitem2 对,我想计算这对出现并在(eligible, shipped, picked) 中有阶段的id 会话计数,并在pair_volume 中填充值。例如,(i1,s1)-(i1,s2) 对出现两次(一次在 id 1 中,一次在 id 3 中)并且在这两个 id 会话中,这对中的两个项目都是 eligible(这是从 @987654340 中暗示的) @ 和 shipped) 阶段。在这对符合条件的配对出现的 2 次中,item1 被拣选、item2 被拣选、item1 发货和 item2 发货了多少次?这就是我要解决的问题。

在交叉连接之前我可以做得很好。但我不知道如何将值插入到交叉连接表中。真正的问题比我在这里提到的要复杂得多。任何帮助深表感谢! 这是我到目前为止的查询:

with new as
(
select combination.item1, combination.subitem1, combination.item2, 
combination.subitem2,
    (
    select tmp.item1, tmp.subitem1, tmp.item2, tmp.subitem2,
    case when ((tmp.item1 = tmp.item2) and 
    (tmp.subitem1 = tmp.subitem2)) then 'TRUE' else 
    'FALSE' end as indicator from
        (
        select distinct item as item1, subitem as subitem2
        from old
        cross join
        select distinct item as item2, subitem as subitem2 
        from old
        ) tmp
    ) combination
where combination.indicator = 'FALSE'
)
insert into new (pair_volume)
select count(id) as pair_volume
from old
where ((new.item1 = old.item) and (new.subitem1 = old.subitem) and 
stage 
in ('picked', 'eligible', 'shipped')) and
((new.item2 = old.item) and (new.subitem2 = old.subitem) and 
stage 
in ('picked', 'eligible', 'shipped')

这基本上是我在这里尝试做的,insert into 语句不断抛出错误。 cross join 之前的部分工作正常。但是我无法将值插入表中,也无法为我想要的输出表设置正确的条件。非常感谢任何帮助!

但是,这会给我带来如下错误:

SQL 编译错误:位置 0 的第 4 行语法错误意外“插入”。

我尝试在 insert into 语句之前包含一个分号,这就是我得到的:

SQL 编译错误:位置 1 的第 3 行语法错误意外';'。

我尝试在insert into 语句之前包含一个逗号,,这就是我得到的:

SQL 编译错误:位置 0 处的第 4 行语法错误意外“插入”。位置 0 处出现语法错误第 5 行意外“选择”。

我在这里做错了什么?根据很多其他帖子,我认为这就是我们如何将 insert into 与 CTE 一起使用。

【问题讨论】:

  • 我删除了不一致的数据库标签。鉴于您的代码在 SQL Server 中运行良好,我强烈建议您使用您真正使用的数据库进行标记。
  • "我首先创建了一个名为'new'的表" - CTE “创建一个表”。您还将示例简化到不再有意义的程度。如所写,您的代码(对于它工作的 DBMS)相当于insert into old select * from old
  • 让我为你们重新提出我的问题
  • @a_horse_with_no_name:我刚刚更新了我的问题,模拟了我试图解决的实际示例,而不是简化版本。
  • 那么您使用的是哪种 DBMS 产品?后格雷斯?甲骨文? SQL 服务器?对我来说,您似乎只是在寻找 create table new as select .... 您不能插入这样的 CTE。你还说你想要这样的“输出”——那么为什么要插入而不只是一个简单的 SELECT 语句?

标签: sql snowflake-cloud-data-platform


【解决方案1】:

如果你没有义务使用CTE(基本上在你想创建新Table的时候使用CTE没有多大意义),你可以试试,比如:

INSERT INTO new (tmp1, tmp2)
SELECT tmp1,tmp2
FROM old

编辑:假设 SQL Server

【讨论】:

    【解决方案2】:

    如 cmets 中所述,您非常接近,但 CTE 不会创建表,这就是它不起作用的原因。

    这点没问题:

    with new as
    (
    select combination.item1, combination.subitem1, combination.item2, 
    combination.subitem2,
        (
        select tmp.item1, tmp.subitem1, tmp.item2, tmp.subitem2,
        case when ((tmp.item1 = tmp.item2) and 
        (tmp.subitem1 = tmp.subitem2)) then 'TRUE' else 
        'FALSE' end as indicator from
            (
            select distinct item as item1, subitem as subitem2
            from old
            cross join
            select distinct item as item2, subitem as subitem2 
            from old
            ) tmp
        ) combination
    where combination.indicator = 'FALSE'
    )
    

    下一行:

    insert into new (pair_volume)
    

    您不能插入新的。没有称为“新”的表。即使您可以插入 CTE,也没有名为 pair_volume 的列。

    您需要创建一个单独的表来包含您正在创建的数据输出。

    您有固定数量的子项吗?如果没有,它会变得更加复杂,您将需要使用动态 SQL 来构建查询以获得所需的结果,或者如果您的 RDBMS 支持它,您可以使用 SELECT INTO 从结果集中动态创建表。

    【讨论】:

    • 在标准 SQL(这是 sql 标签所指的)中,基于 SELECT 语句的新表是使用 CREATE TABLE new AS select ... 而不是“into”创建的
    • 两种方法都有效。请参阅此处了解 SELECT INTO 语法 w3schools.com/sql/sql_select_into.asp
    • @iainc:感谢您的回复。这对我不起作用。我在我的问题中包含了更多细节来模拟我试图解决的问题。非常感谢任何帮助!
    • 好吧,w3fools 以其许多错误而闻名——这就是其中之一。 select into 绝对不是标准 SQL
    • @Gingerbread - 关键是您正在尝试插入 CTE 表。你不能那样做。
    猜你喜欢
    • 1970-01-01
    • 2014-05-25
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    相关资源
    最近更新 更多