MYSQL 从三个表中获取数据
MYSQL getting data from three tables
我正在尝试查找 2020 年 2 月所有饮酒者的饮酒者和在饮料上花费的总金额。我还需要包括在此期间未点酒的饮酒者。
这是三个表格:
CREATE TABLE DRINKERS ( /* All drinkers */
DRINKER VARCHAR(30) NOT NULL,
CONSTRAINT DRINKERS_PKEY PRIMARY KEY (DRINKER));
CREATE TABLE SERVES( /* Pubs serve drinks */
PUB VARCHAR(30) NOT NULL, /* Pub name */
DRINK VARCHAR(30) NOT NULL, /* Drink name */
PRICE DECIMAL(5,2) NOT NULL, /* Drink price */
CONSTRAINT SERVES_PKEY PRIMARY KEY(PUB, DRINK),
CONSTRAINT SERVES_FKEY1 FOREIGN KEY(PUB)
REFERENCES LOCATED(PUB),
CONSTRAINT SERVES_FKEY2 FOREIGN KEY(DRINK)
REFERENCES ALLDRINKS(DRINK) );
CREATE TABLE ORDERS( /* Drinkers visit pubs and consumes drinks */
DRINKER VARCHAR(30) NOT NULL, /* Drinker name */
PUB VARCHAR(30) NOT NULL, /* Pub name */
ODATE DATE NOT NULL, /* Order date */
DRINK VARCHAR(30) NOT NULL, /* Drink name */
DRINK_NO DECIMAL(2) NOT NULL, /* A sequence number of a drink */
CONSTRAINT ORDERS_PKEY PRIMARY KEY(DRINKER, PUB, ODATE, DRINK, DRINK_NO),
CONSTRAINT ORDERS_FKEY1 FOREIGN KEY(PUB, DRINK) REFERENCES SERVES(PUB, DRINK),
CONSTRAINT ORDERS_FKEY2 FOREIGN KEY(DRINKER) REFERENCES DRINKERS(DRINKER) );
到目前为止,这是我的声明:
SELECT ORDERS.DRINKER, SUM(SERVES.PRICE)
FROM ORDERS
LEFT JOIN SERVES ON ORDERS.DRINKER = SERVES.PRICE
GROUP BY ORDERS.DRINKER;
我是SQL的新手,我知道有很多错误。任何帮助将不胜感激!
您可以使用联接作为
SELECT D.DRINKER , SUM(ifnull(S.PRICE,0))
FROM DRINKERS D
LEFT JOIN ORDERS O ON D.DRINKER = O.DRINKER
INNER JOIN SERVES S ON O.PDB = S.PUB
AND S.DRINK = O.DRINK
GROUP BY D.DRINKER;
如果你只需要 2 月
SELECT D.DRINKER , SUM(ifnull(S.PRICE,0))
FROM DRINKERS D
LEFT JOIN ORDERS O ON D.DRINKER = O.DRINKER
AND year(O.ODATE) = 2020 AND month(O.ODATE) = 2
INNER JOIN SERVES S ON O.PDB = S.PUB
AND S.DRINK = O.DRINK
GROUP BY D.DRINKER;
您需要使用简单的 inner join
和 left join
以及 month()
和 year()
函数。无论他们是否点了酒,您都会得到所有饮酒者的结果。因此,您将在 2 月份获得非饮酒者的结果。
select a.drinker,sum(c.price)
from drinkers a left join orders b on a.drinker = b.drinker
join serves c on b.pub = c.pub and b.drink = c.drink
where month(b.odate) = 'February' and year(b.odate) = 2020
group by a.drinker;
由于您想要全部 DRINKERS
,无论他们是否订购,您都希望从 table 开始。然后LEFT JOIN
到ORDERS
table,去拿那些有订单的人。
这是一个猜测,但从 DRINK_NO
列看来,每份饮品在 ORDERS
中有一行。由于您只需要此查询的总饮料,我建议使用 table 的子查询,而不是加入完整的 table。由于此 table 包含 ODATE
数据,您可以在此处的子查询中过滤结果。您也可以在外部查询中使用 WHERE
子句进行过滤,但在此处执行此操作会更有效率。
SELECT
DRINKER,
PUB,
DRINK,
COUNT(DRINK_NO) AS QUANTITY
FROM ORDERS
GROUP BY
DRINKER,
PUB,
DRINK
WHERE
MONTH(ODATE) = 2 AND YEAR(ODATE) = 2020
最后,INNER JOIN
您对 SERVES
的子查询以获得定价信息。
完整构造的查询应该接近于此:
SELECT
d.DRINKER,
SUM(o.PRICE * o.QUANTITY) AS TotalSpent
FROM
DRINKERS AS d
LEFT JOIN
(
SELECT
DRINKER,
PUB,
DRINK,
COUNT(DRINK_NO) AS QUANTITY
FROM ORDERS
GROUP BY
DRINKER,
PUB,
DRINK
WHERE
MONTH(ODATE) = 2 AND YEAR(ODATE) = 2020
) AS o
ON o.DRINKER = d.DRINKER
INNER JOIN SERVES AS s
ON o.PUB = s.PUB
AND o.DRINK = s.DRINK
GROUP BY
d.DRINKER;
有多种查询模式可以return 满足规范的结果。这是一个例子:
SELECT d.drinker AS drinker
, IFNULL(SUM(s.price),0) AS tot_feb_prices
FROM `DRINKERS` d
--
LEFT
JOIN `ORDERS` o
ON o.drinker = p.drinker
AND o.odate >= '2020-02-01'
AND o.odate < '2020-02-01' + INTERVAL 1 MONTH
--
LEFT
JOIN `SERVES` s
ON s.pub = o.pub
AND s.drink = o.drink
--
GROUP
BY d.drinker
ORDER
BY d.drinker
另一种方法是在 select 列表中使用相关子查询(子查询必须 return 标量...只有一列,最多一行。)
SELECT d.drinker
--
, ( SELECT IFNULL(SUM(s.price),0)
FROM `ORDERS` o
JOIN `SERVES` s
ON s.pub = o.pub
AND s.drink = o.drink
WHERE o.drinker = p.drinker
AND o.odate >= '2020-02-01'
AND o.odate < '2020-02-01' + INTERVAL 1 MONTH
) AS tot_feb_prices
--
FROM `DRINKERS` d
ORDER BY d.drinker
我正在尝试查找 2020 年 2 月所有饮酒者的饮酒者和在饮料上花费的总金额。我还需要包括在此期间未点酒的饮酒者。
这是三个表格:
CREATE TABLE DRINKERS ( /* All drinkers */
DRINKER VARCHAR(30) NOT NULL,
CONSTRAINT DRINKERS_PKEY PRIMARY KEY (DRINKER));
CREATE TABLE SERVES( /* Pubs serve drinks */
PUB VARCHAR(30) NOT NULL, /* Pub name */
DRINK VARCHAR(30) NOT NULL, /* Drink name */
PRICE DECIMAL(5,2) NOT NULL, /* Drink price */
CONSTRAINT SERVES_PKEY PRIMARY KEY(PUB, DRINK),
CONSTRAINT SERVES_FKEY1 FOREIGN KEY(PUB)
REFERENCES LOCATED(PUB),
CONSTRAINT SERVES_FKEY2 FOREIGN KEY(DRINK)
REFERENCES ALLDRINKS(DRINK) );
CREATE TABLE ORDERS( /* Drinkers visit pubs and consumes drinks */
DRINKER VARCHAR(30) NOT NULL, /* Drinker name */
PUB VARCHAR(30) NOT NULL, /* Pub name */
ODATE DATE NOT NULL, /* Order date */
DRINK VARCHAR(30) NOT NULL, /* Drink name */
DRINK_NO DECIMAL(2) NOT NULL, /* A sequence number of a drink */
CONSTRAINT ORDERS_PKEY PRIMARY KEY(DRINKER, PUB, ODATE, DRINK, DRINK_NO),
CONSTRAINT ORDERS_FKEY1 FOREIGN KEY(PUB, DRINK) REFERENCES SERVES(PUB, DRINK),
CONSTRAINT ORDERS_FKEY2 FOREIGN KEY(DRINKER) REFERENCES DRINKERS(DRINKER) );
到目前为止,这是我的声明:
SELECT ORDERS.DRINKER, SUM(SERVES.PRICE)
FROM ORDERS
LEFT JOIN SERVES ON ORDERS.DRINKER = SERVES.PRICE
GROUP BY ORDERS.DRINKER;
我是SQL的新手,我知道有很多错误。任何帮助将不胜感激!
您可以使用联接作为
SELECT D.DRINKER , SUM(ifnull(S.PRICE,0))
FROM DRINKERS D
LEFT JOIN ORDERS O ON D.DRINKER = O.DRINKER
INNER JOIN SERVES S ON O.PDB = S.PUB
AND S.DRINK = O.DRINK
GROUP BY D.DRINKER;
如果你只需要 2 月
SELECT D.DRINKER , SUM(ifnull(S.PRICE,0))
FROM DRINKERS D
LEFT JOIN ORDERS O ON D.DRINKER = O.DRINKER
AND year(O.ODATE) = 2020 AND month(O.ODATE) = 2
INNER JOIN SERVES S ON O.PDB = S.PUB
AND S.DRINK = O.DRINK
GROUP BY D.DRINKER;
您需要使用简单的 inner join
和 left join
以及 month()
和 year()
函数。无论他们是否点了酒,您都会得到所有饮酒者的结果。因此,您将在 2 月份获得非饮酒者的结果。
select a.drinker,sum(c.price)
from drinkers a left join orders b on a.drinker = b.drinker
join serves c on b.pub = c.pub and b.drink = c.drink
where month(b.odate) = 'February' and year(b.odate) = 2020
group by a.drinker;
由于您想要全部 DRINKERS
,无论他们是否订购,您都希望从 table 开始。然后LEFT JOIN
到ORDERS
table,去拿那些有订单的人。
这是一个猜测,但从 DRINK_NO
列看来,每份饮品在 ORDERS
中有一行。由于您只需要此查询的总饮料,我建议使用 table 的子查询,而不是加入完整的 table。由于此 table 包含 ODATE
数据,您可以在此处的子查询中过滤结果。您也可以在外部查询中使用 WHERE
子句进行过滤,但在此处执行此操作会更有效率。
SELECT
DRINKER,
PUB,
DRINK,
COUNT(DRINK_NO) AS QUANTITY
FROM ORDERS
GROUP BY
DRINKER,
PUB,
DRINK
WHERE
MONTH(ODATE) = 2 AND YEAR(ODATE) = 2020
最后,INNER JOIN
您对 SERVES
的子查询以获得定价信息。
完整构造的查询应该接近于此:
SELECT
d.DRINKER,
SUM(o.PRICE * o.QUANTITY) AS TotalSpent
FROM
DRINKERS AS d
LEFT JOIN
(
SELECT
DRINKER,
PUB,
DRINK,
COUNT(DRINK_NO) AS QUANTITY
FROM ORDERS
GROUP BY
DRINKER,
PUB,
DRINK
WHERE
MONTH(ODATE) = 2 AND YEAR(ODATE) = 2020
) AS o
ON o.DRINKER = d.DRINKER
INNER JOIN SERVES AS s
ON o.PUB = s.PUB
AND o.DRINK = s.DRINK
GROUP BY
d.DRINKER;
有多种查询模式可以return 满足规范的结果。这是一个例子:
SELECT d.drinker AS drinker
, IFNULL(SUM(s.price),0) AS tot_feb_prices
FROM `DRINKERS` d
--
LEFT
JOIN `ORDERS` o
ON o.drinker = p.drinker
AND o.odate >= '2020-02-01'
AND o.odate < '2020-02-01' + INTERVAL 1 MONTH
--
LEFT
JOIN `SERVES` s
ON s.pub = o.pub
AND s.drink = o.drink
--
GROUP
BY d.drinker
ORDER
BY d.drinker
另一种方法是在 select 列表中使用相关子查询(子查询必须 return 标量...只有一列,最多一行。)
SELECT d.drinker
--
, ( SELECT IFNULL(SUM(s.price),0)
FROM `ORDERS` o
JOIN `SERVES` s
ON s.pub = o.pub
AND s.drink = o.drink
WHERE o.drinker = p.drinker
AND o.odate >= '2020-02-01'
AND o.odate < '2020-02-01' + INTERVAL 1 MONTH
) AS tot_feb_prices
--
FROM `DRINKERS` d
ORDER BY d.drinker