查询错误:错误:在“SELECT”处或附近出现语法错误

Query Error: error: syntax error at or near "SELECT"

提问人:Ashvend 提问时间:10/6/2023 最后编辑:marc_sAshvend 更新时间:10/6/2023 访问量:114

问:

我正在尝试 8weeksqlchallenge,我通常使用 MySQL,那里的错误代码非常干净,但在 dbfiddle.com 上就不那么干净了

这是我的架构

CREATE SCHEMA dannys_diner;
SET search_path = dannys_diner;

CREATE TABLE sales 
(
    "customer_id" VARCHAR(1),
    "order_date" DATE,
    "product_id" INTEGER
);

INSERT INTO sales ("customer_id", "order_date", "product_id")
VALUES
  ('A', '2021-01-01', '1'),
  ('A', '2021-01-01', '2'),
  ('A', '2021-01-07', '2'),
  ('A', '2021-01-10', '3'),
  ('A', '2021-01-11', '3'),
  ('A', '2021-01-11', '3'),
  ('B', '2021-01-01', '2'),
  ('B', '2021-01-02', '2'),
  ('B', '2021-01-04', '1'),
  ('B', '2021-01-11', '1'),
  ('B', '2021-01-16', '3'),
  ('B', '2021-02-01', '3'),
  ('C', '2021-01-01', '3'),
  ('C', '2021-01-01', '3'),
  ('C', '2021-01-07', '3');
 
CREATE TABLE menu 
(
    "product_id" INTEGER,
    "product_name" VARCHAR(5),
    "price" INTEGER
);

INSERT INTO menu ("product_id", "product_name", "price")
VALUES
  ('1', 'sushi', '10'),
  ('2', 'curry', '15'),
  ('3', 'ramen', '12');
  

CREATE TABLE members 
(
    "customer_id" VARCHAR(1),
    "join_date" DATE
);

INSERT INTO members ("customer_id", "join_date")
VALUES
  ('A', '2021-01-07'),
  ('B', '2021-01-09');

询问是找到每个客户购买的第一个产品,所以我想到使用以下代码的子查询,但它返回了

查询错误:错误:在“SELECT”处或附近出现语法错误

SELECT sales.customer_id, sales.product_id
FROM dannys_diner.sales 
WHERE sales.order_date = SELECT MIN(sales.order_date)
                         FROM dannys_diner.sales 
                         GROUP BY sales.customer_id;
SQL PostgreSQL 选择 子查询

评论

1赞 Sergey 10/6/2023
请执行您的 SELECT MIN(sales.order_date) FROM dannys_diner.SALES GROUP BY sales.customer_id,并查看您有几个日期。我怀疑即使你修复语法错误,你也会得到不正确的结果
1赞 Frank Heikens 10/6/2023
A的正确答案是什么?1、2 或 1 和 2

答:

0赞 Hogan 10/6/2023 #1

你需要并围绕子查询 -- 像这样()

SELECT sales.customer_id, sales.product_id
FROM dannys_diner.sales
WHERE sales.order_date = ( 
  SELECT MIN(sales.order_date)
  FROM dannys_diner.sales 
  GROUP BY sales.customer_id
);

正如一些人所指出的,可能会有一些数据会导致一个问题,联接可以解决这个问题,因为你可以确保最小数字是按customer_id -- 像这样

SELECT sales.customer_id, sales.product_id
FROM dannys_diner.sales
JOIN ( 
  SELECT MIN(sales.order_date) as order_date, sales.customer_id
  FROM dannys_diner.sales 
  GROUP BY sales.customer_id
) as x on x.order_date = sales.order_date and x.customer_id = sales.customer_id ;

请注意,如果您使用我的代码比较小提琴

https://dbfiddle.uk/CSKDTxd6

对于 Joel 的回答(使用窗口函数),您可以看到我们得到了不同的结果——如果它们的日期相同,我将返回不止一行——他只会返回一行。选择符合您要求的哪一个:

评论

1赞 nbk 10/6/2023
GROUP BY 返回多个列,因此会带来错误
0赞 Sergey 10/6/2023
@Hogan。我想,问题是客户 1 分钟日期是 1 月 1 日,但客户 2 分钟日期是 8 月 1 日
0赞 Frank Heikens 10/6/2023
子查询为每个sales.customer_id返回一条记录。外部查询仅排除一个结果。此冲突将导致错误。
0赞 Hogan 10/6/2023
我写了一个修复程序 - 感谢您的评论:)
2赞 Joel Coehoorn 10/6/2023 #2

这里有两个语法错误。

首先,子查询需要括在括号中。这很容易补救。

其次,为了在等式比较的右侧有效,必须保证子查询始终返回单个值。子查询中的子句打破了这一点,因为它允许每个客户 ID 有单独的最小订单日期。这更难解决,因为这意味着要重新思考查询的结构。sales.order_dateGROUP BY

相反,我建议使用窗口函数按日期识别行,然后从行中显示产品,而无需相关的每行子查询或 JOIN(换句话说,它应该快得多):row_number()

SELECT customer_id, product_id
FROM (
    select sales.customer_id, sales.product_id
        , row_number() over (partition by customer_id order by sales.order_date) rn
    from dannys_diner.sales
) t
WHERE rn = 1

https://dbfiddle.uk/YGdol5Rd

评论

0赞 Joel Coehoorn 10/6/2023
另外,关于我使用大写的说明
0赞 Hogan 10/6/2023
我认为对于简单的情况,缩进就足够了,但我可能会在一个非常复杂的查询中使用这个技巧——乔尔,这是个好主意。
0赞 Frank Heikens 10/6/2023
随着时间的流逝,当添加更多记录时,此速度会变慢。
0赞 nbk 10/6/2023 #3

您可以加入 subqzery 以获得您想要的结果

SELECT s1.customer_id, s1.product_id
FROM dannys_diner.sales s1 JOIN
  (SELECT customer_id,MIN(order_date) min_date
FROM dannys_diner.sales 
GROUP BY sales.customer_id) s2  ON s1.customer_id = s2.customer_id
  ANd s1.order_date = s2.min_date
  
;

customer_id product_id
一个 1
一个 2
B 2
C 3
C 3
SELECT 5

小提琴

评论

0赞 Hogan 10/6/2023
这和我的缩进错误答案不一样吗?