Sql 通过执行多个联接来避免运行多个查询,这是不可能的

Sql 通过执行多个联接来避免运行多个查询,这是不可能的,sql,ms-access,Sql,Ms Access,我真的被这个SQL困住了。我有两个MS Access数据库表设置,如下所示: 数据表 monthdata表 我不想改变这个表的结构。我在monthdata表中有几个月的数据,它与数据表中的引用相关联 我试图在一个查询和一行中返回三个月的数据,如下所示: UID - MONTHVAL - VAL - MONTHVAL - VAL - MONTHVAL - VAL 因此,如果我们想要获取UID ABC123的最后三个月数据,我尝试运行以下查询: SELECT data.uid, monthda

我真的被这个SQL困住了。我有两个MS Access数据库表设置,如下所示:

数据表

monthdata表

我不想改变这个表的结构。我在monthdata表中有几个月的数据,它与数据表中的引用相关联

我试图在一个查询和一行中返回三个月的数据,如下所示:

UID - MONTHVAL - VAL - MONTHVAL - VAL - MONTHVAL - VAL  
因此,如果我们想要获取UID ABC123的最后三个月数据,我尝试运行以下查询:

SELECT data.uid, monthdata.monthval, monthdata.val
FROM data
LEFT JOIN monthdata ON data.UID = monthdata.dataUID AND monthdata.monthval = "01/09/2018"
LEFT JOIN monthdata ON data.UID = monthdata.dataUID AND monthdata.monthval = "01/08/2018"
LEFT JOIN monthdata ON data.UID = monthdata.dataUID AND monthdata.monthval = "01/07/2018"
WHERE UID = 'ABC123'

但是它告诉我这是无效的语法。然而,尽管我在谷歌上搜索,我还是不知道该怎么做。我能看到的唯一选择是运行三个单独的查询,并将日期放在WHERE中,但在现实世界的示例中,我有更多的月份。

尝试下面的行数和case when

    select uid, 
    max(case when  rn=1 then  monthval end) as month1, 
    max(case when  rn=1 then  val end) as val1,
    max(case when  rn=2 then  monthval end) as month2,
    max(case when  rn=2 then  val end) as val2,
    max(case when  rn=3 then  monthval end) as month3, 
    max(case when  rn=3 then  val end) as val3
    from
    (
      SELECT data.uid, monthdata.monthval, monthdata.val,row_number() over(order by uid) as rn FROM data
      LEFT JOIN monthdata ON data.UID = monthdata.dataUID and monthdata.monthval between '01/07/2018' and '01/09/2018'
WHERE UID = 'ABC123')a
      group by uid

当您像使用monthval一样多次加入表时,每次都必须使用不同的别名。当然,在这种情况下,改变DB模式是Youo应该考虑的,不管怎样,语法错误来自缺少的别名,请尝试这样:

SELECT D.uid, M.monthval, M1.monthval, M2.monthval
FROM ((data AS D
LEFT JOIN monthdata AS M ON D.UID = M.dataUID AND M.monthval = #01/09/2018#)
LEFT JOIN monthdata AS M1 ON D.UID = M1.dataUID AND M1.monthval = #01/08/2018#) 
LEFT JOIN monthdata AS M2 ON D.UID = M2.dataUID AND M2.monthval = #01/07/2018#
WHERE UID = 'ABC123';

在上面的例子中,我使用了三个别名来表示月份数据M、M1和M2,一个别名表示数据D,在select中我输入M1和M2,但是您可以输入您需要的别名。

您的查询有一些问题。一是缺少别名。另一个是MS Access需要大量多余的括号来连接:

SELECT d.uid, md_20180901.val, md_20180801.val, md_20180701.val
FROM ((data as d LEFT JOIN
       (SELECT md.*
        FROM monthdata md
        WHERE md.monthval = "01/09/2018"
       ) as md_20180901
       ON d.UID = md_20180901.dataUID
      ) LEFT JOIN
      (SELECT md.*
       FROM monthdata md
       WHERE md.monthval = "01/08/2018"
      ) as md_20180801
      ON d.UID = md_20180801.dataUID AND md_20180801.monthval = "01/08/2018"
     ) LEFT JOIN
     (SELECT md.*
      FROM monthdata md
      WHERE md.monthval = "01/07/2018"
     ) as md_20180701
     ON d.UID = md_20180701.dataUID AND md_20180701.monthval = "01/07/2018"
WHERE d.UID = "ABC123";
您还可以使用条件聚合来表示这一点:

SELECT d.uid,
       MAX(IIF(md.monthval = "01/09/2018", val, NULL)) as mv_20180901,
       MAX(IIF(md.monthval = "01/08/2018", val, NULL)) as mv_20180801,
       MAX(IIF(md.monthval = "01/07/2018", val, NULL)) as mv_20180701
FROM data as d LEFT JOIN
     monthdata as md
     ON d.UID = md.dataUID 
WHERE d.UID = "ABC123"
GROUP BY d.UID;

当我尝试这一点时,a将其减少一点,并最终从数据D中选择D.uid、M1.monthval、M2.val在D.uid=M.dataUID和M.monthval=01/01/2018上左连接monthdata M,其中uid='ABC123',但我得到的错误连接表达式不受支持您需要D=M.dataUID和M.monthval=01/2018上的括号,我将编辑我的答案很抱歉,这很麻烦,但我在查询中得到了错误语法error missing运算符expression@LaBracca原来这只是把括号放在正确的地方的问题。@SalmanA这是我的错误,因为我在stackoverflow中键入了解决方案,而不是在ManagementStudio中键入的,无论如何,我在您的编辑,我不理解你的编辑,我想我花了太多时间来回答这个问题,我会离开的,谢谢你。我尝试运行此操作,但在查询表达式“row_number overorder by uid”中获取了错误语法错误缺少运算符。您正在使用哪个数据库?Access数据库,很抱歉,我应该mentioned@Jimmy . . . MS访问的另一个限制。我认为子查询可以解决这个问题。但是第二种方法也应该有效。@Jimmy。4投反对票的绝对不是你;我想这是堆栈溢出的糟糕一天。我不明白为什么。我注意到一个完全不合适的答案被投了赞成票。哈哈,我在这里投了反对票,到目前为止,有大约1000张赞成票/0张反对票的答案有2张。@SalmanA。绝对没有理由对你的答案投反对票。我指的是带有行号的答案。@GordonLinoff它是在OP指定他使用ms access之前发布的,可能是向上投票的。交叉表查询不能实现这一点吗?或者至少是非常接近的东西?
SELECT d.uid, md_20180901.val, md_20180801.val, md_20180701.val
FROM ((data as d LEFT JOIN
       (SELECT md.*
        FROM monthdata md
        WHERE md.monthval = "01/09/2018"
       ) as md_20180901
       ON d.UID = md_20180901.dataUID
      ) LEFT JOIN
      (SELECT md.*
       FROM monthdata md
       WHERE md.monthval = "01/08/2018"
      ) as md_20180801
      ON d.UID = md_20180801.dataUID AND md_20180801.monthval = "01/08/2018"
     ) LEFT JOIN
     (SELECT md.*
      FROM monthdata md
      WHERE md.monthval = "01/07/2018"
     ) as md_20180701
     ON d.UID = md_20180701.dataUID AND md_20180701.monthval = "01/07/2018"
WHERE d.UID = "ABC123";
SELECT d.uid,
       MAX(IIF(md.monthval = "01/09/2018", val, NULL)) as mv_20180901,
       MAX(IIF(md.monthval = "01/08/2018", val, NULL)) as mv_20180801,
       MAX(IIF(md.monthval = "01/07/2018", val, NULL)) as mv_20180701
FROM data as d LEFT JOIN
     monthdata as md
     ON d.UID = md.dataUID 
WHERE d.UID = "ABC123"
GROUP BY d.UID;