我正在尝试对数据进行分类,因为我从表中提取数据。数据具有通过每行中的“valid_from”和“valid_to”日期字段保存的历史记录。
我想提取数据并按如下方式对其进行限定:
NEW => WHERE CURRENT_DATE BETWEEN valid_from AND (valid_from + 1 MOTNH)
CURRENT => WHERE CURRENT_DATE > (valid_from + 1 MOTNH)
RETIRED => the rest of the rows, so the "dish_id" items not in the tables above, BUT
returning the values from the row containing MAX(valid_to) date.
我这样做是最好/更有效的方式吗?提前谢谢!
SELECT
menu_table.dish_id,
menu_table.dish_title,
menu_table.marketing_desc,
menu_table_status.rrp_inc_gst,
menu_table_status.lowest_rrp,
menu_table_status.highest_rrp,
'n' as status
FROM
menu_table,
menu_table_status
WHERE
CURRENT_DATE BETWEEN menu_table_status.valid_from_date AND DATE_ADD(menu_table_status.valid_from_date, INTERVAL 1 MONTH)
AND CURRENT_DATE < menu_table_status.valid_to_date
AND menu_table.dish_id = menu_table_status.dish_id
UNION
SELECT
menu_table.dish_id,
menu_table.dish_title,
menu_table.marketing_desc,
menu_table_status.rrp_inc_gst,
menu_table_status.lowest_rrp,
menu_table_status.highest_rrp,
'c' as status
FROM
menu_table,
menu_table_status
WHERE
CURRENT_DATE > DATE_ADD(menu_table_status.valid_from_date, INTERVAL 1 MONTH)
AND CURRENT_DATE < menu_table_status.valid_to_date
AND menu_table.dish_id = menu_table_status.dish_id
UNION
SELECT
menu_table.dish_id,
menu_table.dish_title,
menu_table.marketing_desc,
menu_table_status.rrp_inc_gst,
menu_table_status.lowest_rrp,
menu_table_status.highest_rrp,
'r' as status
FROM
menu_table,
menu_table_status
WHERE
menu_table_status.valid_to_date
AND menu_table.dish_id NOT IN (SELECT inside_table1.dish_id
FROM menu_table_status AS inside_table1
WHERE CURRENT_DATE BETWEEN inside_table1.valid_from_date
AND inside_table1.valid_to_date)
AND menu_table_status.valid_to_date = (SELECT MAX(inside_table2.valid_to_date)
FROM menu_table_status AS inside_table2
WHERE inside_table2.dish_id = menu_table_status.dish_id)
AND menu_table.dish_id = menu_table_status.dish_id
答案 0 :(得分:1)
如果没有多看,你肯定会在最后的where子句中混淆日期。无论如何,你的陈述是复杂的。只需选择所有记录(无论如何都要做)并查看每个记录的日期以确定要给出的状态:
SELECT
menu_table.dish_id,
menu_table.dish_title,
menu_table.marketing_desc,
menu_table_status.rrp_inc_gst,
menu_table_status.lowest_rrp,
menu_table_status.highest_rrp,
CASE
WHEN
CURRENT_DATE BETWEEN menu_table_status.valid_from_date AND DATE_ADD(menu_table_status.valid_from_date, INTERVAL 1 MONTH)
AND CURRENT_DATE < menu_table_status.valid_to_date
THEN 'n'
WHEN
CURRENT_DATE > DATE_ADD(menu_table_status.valid_from_date, INTERVAL 1 MONTH)
AND CURRENT_DATE < menu_table_status.valid_to_date
THEN 'c'
ELSE 'r'
END as status
FROM menu_table
INNER JOIN menu_table_status ON menu_table.dish_id = menu_table_status.dish_id;
BTW:请不要使用旧的连接语法,列出所有以逗号分隔的表。它容易出错,这就是为什么从1992年开始有一种“新”语法的原因。
编辑:我发现了你的错误。您只需检查CURRENT_DATE < menu_table_status.valid_to_date
,而不是检查menu_table_status.valid_to_date
,因此将日期视为布尔值,这在MySQL中是特殊的。
还有一句话:当联合集合是不同的(你的是由于不同的状态字母)时,使用UNION ALL,而不是UNION。 UNION用于删除重复项。为什么dbms会在您知道没有重复项时检查所有记录?
答案 1 :(得分:0)
如果您不需要一次性执行此操作,我建议将第一步提取到一个临时表中,然后将第二步定义为dish_id与该临时表的左连接,其中dish_id为NULL:
CREATE TEMPORARY TABLE step1 AS (
SELECT
mt.dish_id,
mt.dish_title,
mt.marketing_desc,
mts.rrp_inc_gst,
mts.lowest_rrp,
mts.highest_rrp,
(
if(CURRENT_DATE<DATE_ADD(mts.valid_from_date, INTERVAL 1 MONTH),
'n', 'c')
) as status
FROM
menu_table mt
JOIN menu_table_status mts ON mt.dish_id=mts.dish_id
WHERE CURRENT_DATE BETWEEN mts.valid_from_date AND mts.valid_to_date-1
);
SELECT step1.*
UNION
SELECT
mt.dish_id,
mt.dish_title,
mt.marketing_desc,
mts.rrp_inc_gst,
mts.lowest_rrp,
mts.highest_rrp,
'r' as status
FROM
menu_table mt
LEFT JOIN step1 s1 on s1.dish_id=mt.dish_id WHERE s1.dish_id is NULL
JOIN menu_table_status mts ON mt.dish_id=mts.dish_id;