如何逐个写出正确的顺序

How to write a correct order by case

我有这个问题,如果我正常使用sql语句,我的意思是这样的:

SELECT p.id_plecari, p.id_aeroport, p.id_clasa, p.id_avion, p.data, p.ora, c.pret, av.nume, a.Nume, a.Locatie
    from plecari p, clasa c, avioane av, aeroport a
where 
   p.id_aeroport = a.id_aeroport
   AND p.id_clasa = c.id_clasa
   AND p.id_avion = av.id_avion
   AND p.id_plecari not in(SELECT r.id_plecare from rezervari r WHERE r.id_client = idClient) 
   ORDER BY p.id_clasa ASC;

一切都如我所料,完美如 this picture
但是在我添加 CASE 语句的那一刻,一切都搞砸了:

BEGIN
SELECT p.id_plecari, p.id_aeroport, p.id_clasa, p.id_avion, p.data, p.ora, c.pret, av.nume, a.Nume, a.Locatie
    from plecari p, clasa c, avioane av, aeroport a
    where 
        p.id_aeroport = a.id_aeroport
        AND p.id_clasa = c.id_clasa
        AND p.id_avion = av.id_avion
        AND p.id_plecari not in(SELECT r.id_plecare from rezervari r WHERE r.id_client = idClient) ORDER BY 
        (CASE 
    WHEN (orderby = 1 AND orderas = false) THEN p.id_plecari
    WHEN (orderby = 2 AND orderas = false) THEN av.nume
  END) ASC ,
  (CASE 
    WHEN (orderby = 1 AND orderas = true) THEN p.id_plecari
    WHEN (orderby = 2 AND orderas = true) THEN av.nume
  END) DESC;
END

一切看起来 like this!

SELECT
  p.id_plecari, p.id_aeroport, p.id_clasa, p.id_avion, p.data, p.ora, c.pret, av.nume, a.Nume, a.Locatie
FROM
  plecari   p
INNER JOIN
  clasa     c
    ON p.id_clasa = c.id_clasa
INNER JOIN
  avioane   av
    ON p.id_avion = av.id_avion
INNER JOIN
  aeroport  a
    ON p.id_aeroport = a.id_aeroport
WHERE
  p.id_plecari not in (
    SELECT r.id_plecare from rezervari r WHERE r.id_client = idClient
  )
ORDER BY 
  CASE WHEN (orderby = 1 AND orderas = false) THEN p.id_plecari END,
  CASE WHEN (orderby = 2 AND orderas = false) THEN av.nume      END,
  CASE WHEN (orderby = 1 AND orderas = true ) THEN p.id_plecari END DESC,
  CASE WHEN (orderby = 2 AND orderas = true ) THEN av.nume      END DESC;

这说明了如何使用 JOIN,以及如何将 ORDER BY 分成几部分。

但是请注意,这种“条件排序”样式的性能可能非常差。

这是因为数据库必须生成一个执行计划来满足所有可能性。

性能更高的方法是将主查询作为视图,然后有类似于...

IF (orderby = 1 AND orderas = false) THEN
  SELECT * FROM yourView ORDER BY p.id_plecari;
ELSEIF (orderby = 2 AND orderas = false) THEN
  SELECT * FROM yourView ORDER BY av.nume;
ELSEIF (orderby = 1 AND orderas = true) THEN
  SELECT * FROM yourView ORDER BY p.id_plecari DESC;
ELSEIF (orderby = 2 AND orderas = true) THEN
  SELECT * FROM yourView ORDER BY av.nume DESC;
ENDIF;

这允许每个排序模式有不同的执行计划。

  • This 解释得更详细