需要您的帮助人员来构成查询。
示例。公司-租车
桌子-汽车
ID NAME STATUS
1 Mercedes Showroom
2 Mercedes On-Road
现在,如何从此表中仅选择一个满足以下条件的条目?
如果梅赛德斯陈列室有售,则仅获取该行。 (即上例中的第1行)
但是,如果陈列室中没有一辆梅赛德斯奔驰,请提取其中任何一排。 (即第1行或第2行)-(这只是说所有的奔驰车都在路上)
在这里使用独特的方法无济于事,因为在选择语句中也获取了ID
谢谢!
MySQL没有排名/分析/窗口功能,但是您可以使用变量来模拟ROW_NUMBER功能(当看到“-”时,是注释):
SELECT x.id, x.name, x.status
FROM (SELECT t.id,
t.name,
t.status,
CASE
WHEN @car_name != t.name THEN @rownum := 1 -- reset on diff name
ELSE @rownum := @rownum + 1
END AS rank,
@car_name := t.name -- necessary to set @car_name for the comparison
FROM CARS t
JOIN (SELECT @rownum := NULL, @car_name := '') r
ORDER BY t.name, t.status DESC) x --ORDER BY is necessary for rank value
WHERE x.rank = 1
按状态排序DESC表示“陈列室”将位于列表的顶部,因此它将排名为1。如果汽车名称不具有“陈列室”状态,则排为1的行将为“陈列室”之后是什么状态。 WHERE子句将仅返回表中每辆车的第一行。
状态是基于文本的数据类型,告诉我您的数据未规范化-我可以添加带有“ Showroom”,“ SHOWroom”和“ showROOM”的记录。它们是有效的,但是当您将事物分组以进行计数,求和等时,您正在考虑使用LOWER和UPPER之类的功能。使用这些功能还会使该列上的索引无用...您将要考虑制作一个CAR_STATUS_TYPE_CODE表,并使用外键关系来确保不良数据不会进入您的表:
DROP TABLE IF EXISTS `example`.`car_status_type_code`;
CREATE TABLE `example`.`car_status_type_code` (
`car_status_type_code_id` int(10) unsigned NOT NULL auto_increment,
`description` varchar(45) NOT NULL default '',
PRIMARY KEY (`car_status_type_code_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
这是解决该问题的常用方法:
SELECT *,
CASE STATUS
WHEN 'Showroom' THEN 0
ELSE 1
END AS InShowRoom
FROM Cars
WHERE NAME = 'Mercedes'
ORDER BY InShowRoom
LIMIT 1
这里介绍了如何获得所有汽车,这也显示了解决问题的另一种方法:
SELECT ID, NAME, IFNULL(c2.STATUS, c1.STATUS)
FROM Cars c1
LEFT OUTER JOIN Cars c2
ON c2.NAME = c1.NAME AND c2.STATUS = 'Showroom'
GROUP BY NAME
ORDER BY NAME
您可能想使用FIND_IN_SET()
功能来做到这一点。
FIND_IN_SET()
如果您具有其他状态的首选顺序,只需将它们添加到第二个参数中。
SELECT *
FROM Cars
WHERE NAME = 'Mercedes'
ORDER BY FIND_IN_SET(`STATUS`,'Showroom') DESC
LIMIT 1
要获取所有汽车的“最佳”状态,您只需执行以下操作:
ORDER BY FIND_IN_SET(`STATUS`,'On-Road,Showroom' ) DESC
SELECT *
FROM Cars
GROUP BY NAME
ORDER BY FIND_IN_SET(`STATUS`,'Showroom') DESC
EDIT删除了UNION上的ALL,因为我们始终只需要不同的行。