MySQL UNION 中语句求值和变量赋值的顺序

发布于 2024-12-22 06:55:12 字数 1496 浏览 1 评论 0原文

问题:在下面的 UNIONized 查询中,如何在评估依赖的派生查询之前强制分配 @col?要求:需要在一次查询中完成。

CREATE TABLE tbl (col CHAR(1) NOT NULL UNIQUE);

INSERT INTO tbl (col) VALUES ('a'), ('b'), ('c'), ('d'), ('e'), ...;

-- Now, for some value of "col", fetch that record and the
-- immediately preceding and following records as ordered by "col"
--
-- If you care to test this, be sure to SET @col := NULL before
-- subsequent executions to simulate a "fresh" MySQL session...
--
SELECT @col := col AS col    -- Fetch particular record given a value of
  FROM tbl                   -- "col".
 WHERE col = 'd'
UNION ALL
SELECT col                   -- Fetch the immediately preceding record,
  FROM (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col < @col
        ORDER BY col DESC
          LIMIT 1) preceding
UNION ALL
SELECT col                   -- Fetch the immediately following record,
  FROM (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col > @col
        ORDER BY col ASC
          LIMIT 1) following
ORDER BY col ASC;

背景:从上面的 UNIONized 查询中,我期望获得三个记录:一条与精确且唯一的“col”值匹配的记录,以及按“col”排序的紧邻的前一个和后一个记录。

但是,第一次运行查询仅生成一条记录,该记录与用户提供的“col”值相匹配。随后的运行给了我我期望的三个。我的推断是,直到派生查询 precedingfollowing 被评估之后,@col 才会被分配 - 这不是从左到右的-我期望的从上到下的评估顺序。

(我试图完善这个问题的答案,但遇到了这个困难。)

Question: In the UNIONized query below, how can I force @col to be assigned before the dependent derived queries are evaluated? Requirement: it needs to be done in one query.

CREATE TABLE tbl (col CHAR(1) NOT NULL UNIQUE);

INSERT INTO tbl (col) VALUES ('a'), ('b'), ('c'), ('d'), ('e'), ...;

-- Now, for some value of "col", fetch that record and the
-- immediately preceding and following records as ordered by "col"
--
-- If you care to test this, be sure to SET @col := NULL before
-- subsequent executions to simulate a "fresh" MySQL session...
--
SELECT @col := col AS col    -- Fetch particular record given a value of
  FROM tbl                   -- "col".
 WHERE col = 'd'
UNION ALL
SELECT col                   -- Fetch the immediately preceding record,
  FROM (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col < @col
        ORDER BY col DESC
          LIMIT 1) preceding
UNION ALL
SELECT col                   -- Fetch the immediately following record,
  FROM (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col > @col
        ORDER BY col ASC
          LIMIT 1) following
ORDER BY col ASC;

Background: From the UNIONized query above I expected to obtain three records: a record matching an exact and unique "col" value, and the immediately preceding and following records as ordered by "col".

However, the first run of the query yields just one record, the one matching the user-supplied value for "col". Subsequent runs give me the three I expect. My inference is that @col is not assigned until after the derived queries preceding and following are evaluated — that was not the left-to-right-top-to-bottom evaluation order I'd expected.

(I was attempting to refine an answer to this question, but ran in to this difficulty.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

赴月观长安 2024-12-29 06:55:12

不要将 @col 的分配与其他查询联合起来。

使用一个查询为 @col 分配一个值,并使用一个单独的查询将该记录包含在结果中。

SELECT @col := col AS col    -- Fetch particular record given a value of
  FROM tbl                   -- "col", assigning the identifier to @col.
 WHERE col = 'd'



SELECT col                   -- Now include the above record in the
  FROM tbl                   -- Final result-set
WHERE col = @col

UNION ALL

SELECT col                   -- Fetch the immediately preceding record,
  FROM (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col < @col
        ORDER BY col DESC
          LIMIT 1) preceding

UNION ALL

SELECT col                   -- Fetch the immediately following record,
  FROM (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col > @col
        ORDER BY col ASC
          LIMIT 1) following
ORDER BY col ASC;

Don't UNION the assignment of @col with your other queries.

Have one query to assign a value to @col, and a separate query to include that record in your results.

SELECT @col := col AS col    -- Fetch particular record given a value of
  FROM tbl                   -- "col", assigning the identifier to @col.
 WHERE col = 'd'



SELECT col                   -- Now include the above record in the
  FROM tbl                   -- Final result-set
WHERE col = @col

UNION ALL

SELECT col                   -- Fetch the immediately preceding record,
  FROM (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col < @col
        ORDER BY col DESC
          LIMIT 1) preceding

UNION ALL

SELECT col                   -- Fetch the immediately following record,
  FROM (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col > @col
        ORDER BY col ASC
          LIMIT 1) following
ORDER BY col ASC;
装迷糊 2024-12-29 06:55:12
SELECT @col := col AS col    -- Fetch particular record given a value of
  FROM tbl                   -- "col".
 WHERE col = 'd'
UNION ALL
SELECT col                   -- Fetch the immediately preceding record,
  FROM

(@colx:=col), -- Assigne it here

       (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col < @colx
        ORDER BY col DESC
          LIMIT 1) preceding
UNION ALL
SELECT col                   -- Fetch the immediately following record,
  FROM

(@colx:=col), -- Assign it here also

       (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col > @colx
        ORDER BY col ASC
          LIMIT 1) following
ORDER BY col ASC;
SELECT @col := col AS col    -- Fetch particular record given a value of
  FROM tbl                   -- "col".
 WHERE col = 'd'
UNION ALL
SELECT col                   -- Fetch the immediately preceding record,
  FROM

(@colx:=col), -- Assigne it here

       (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col < @colx
        ORDER BY col DESC
          LIMIT 1) preceding
UNION ALL
SELECT col                   -- Fetch the immediately following record,
  FROM

(@colx:=col), -- Assign it here also

       (  SELECT col         -- ordered by "col"
            FROM tbl
           WHERE col > @colx
        ORDER BY col ASC
          LIMIT 1) following
ORDER BY col ASC;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文