Search code examples
sqlsql-serverquery-optimization

Optimization of SQL query with multiple unions


Does anybody know how to make this query a bit shorter? The problem, and reason why I am asking this is is that it takes a long time to process the query because the query returns over 16K records.

SELECT p.broj, p.mje_osig, p.id_cjen, p.poc_dat, p.ist_dat, ' ' AS nac_prem,
         1 AS gr_red, s.rbr, s.serial, s.vs, s.stat_id, s.naziv, 
         s.osnov*s.kol_dok AS osnovica, s.stopa, s.premija*s.kol_dok AS premija 
     FROM osiguranje.police_osn p, osiguranje.st_pol s 
     WHERE p.broj=s.broj AND 
        XUvjet+ AND s.vs='SO' AND s.premija<>0 
UNION ALL 
SELECT p.broj, p.mje_osig, p.id_cjen, p.poc_dat, p.ist_dat, ' ' AS nac_prem, 
        1 AS gr_red, s.rbr, s.serial, s.vs, s.stat_id, s.naziv, 
        s.osnov AS osnovica, s.stopa, s.premija 
     FROM osiguranje.police_osn p, osiguranje.st_pol s 
     WHERE p.broj=s.broj AND 
        XUvjet AND s.vs='DO' AND s.premija<>0 
UNION ALL 
SELECT p.broj, p.mje_osig, p.id_cjen, p.poc_dat, p.ist_dat, ' ' AS nac_prem, 
        1 AS gr_red, s.rbr, s.serial, s.vs, s.stat_id, s.naziv, 
        s.osnov AS osnovica, s.stopa, -s.premija AS premija 
    FROM osiguranje.police_osn p, osiguranje.st_pol s 
    WHERE p.broj=s.broj AND 
        XUvjet AND s.vs='PO' AND s.premija<>0 
UNION ALL 
SELECT p.broj, p.mje_osig, p.id_cjen, p.poc_dat, p.ist_dat, ' ' AS nac_prem, 
         1 AS gr_red, s.rbr, s.serial, s.vs, s.stat_id, s.naziv, 
         s.osnov*s.kol_dok AS osnovica, s.stopa, s.premija*s.kol_dok AS premija 
    FROM osiguranje.police_osn p, osiguranje.st_pril s 
    WHERE p.broj=s.broj AND 
        XUvjet AND s.vs='SO' AND s.premija<>0 
UNION ALL 
SELECT p.broj, p.mje_osig, p.id_cjen, p.poc_dat, p.ist_dat, ' ' AS nac_prem, 
        1 AS gr_red, s.rbr, s.serial, s.vs, s.stat_id, s.naziv, 
        s.osnov AS osnovica, s.stopa, s.premija 
    FROM osiguranje.police_osn p, osiguranje.st_pril s 
    WHERE p.broj=s.broj AND 
        XUvjet AND s.vs='DO' AND s.premija<>0 
UNION ALL 
SELECT p.broj, p.mje_osig, p.id_cjen, p.poc_dat, p.ist_dat, ' ' AS nac_prem, 
        1 AS gr_red, s.rbr, s.serial, s.vs, s.stat_id, s.naziv, 
        s.osnov AS osnovica, s.stopa, -s.premija AS premija 
    FROM osiguranje.police_osn p, osiguranje.st_pril s 
    WHERE p.broj=s.broj AND 
        XUvjet AND s.vs='PO' AND s.premija<>0 
UNION ALL 
SELECT p.broj, p.mje_osig, p.id_cjen, p.poc_dat, p.ist_dat, q.nac_prem, 
        0 AS gr_red, s.rbr, s.serial, s.vs, s.stat_id, s.naziv, 
        s.osnov AS osnovica, s.stopa, s.premija 
    FROM osiguranje.police_osn p, osiguranje.skup_os q, osiguranje.st_pol s 
    WHERE p.proizvod=q.sifra AND p.broj=s.broj AND 
        XUvjet AND s.vs='DK' AND s.stopa<>0 
UNION ALL 
SELECT p.broj, p.mje_osig, p.id_cjen, p.poc_dat, p.ist_dat, q.nac_prem, 
        0 AS gr_red, s.rbr, s.serial, s.vs, s.stat_id, s.naziv, 
        s.osnov AS osnovica, -s.stopa AS stopa, s.premija 
    FROM osiguranje.police_osn p, osiguranje.skup_os q, osiguranje.st_pol s 
    WHERE p.proizvod=q.sifra AND p.broj=s.broj AND 
        XUvjet  AND s.vs='PK' AND s.stopa<>0 
ORDER BY p.broj, gr_red, s.rbr, s.serial 

XUvjet is a variable that'll be inserted in a C# code.


Solution

  • For the s.vs in WHERE clause you can easily use the IN operator:

    WHERE s.vs IN ['PK', 'DK', 'PO', ...]
    

    For the gr_red in SELECT clause you can use the CASE-WHEN operator:

    SELECT  ' ' AS nac_prem, gr_red =
          CASE
             WHEN s.vs='PK' THEN 0
             WHEN  XUvjet AND s.vs='PO' THEN 1
             ELSE 1
          END,
    

    Obviously you can add more logic to the WHEN clause here to make it fit the logic of your query.