English 中文(简体)
Improving SQL Code
原标题:

I m using Pervasive SQL. I have the following UNION of mulitple SQL statements. Is there a way to clean this up, especially the Pay Date an the Loc No fields that are selected in each statement. Is there a way to pull this out and have only one place to need to change those two fields?

(
    SELECT 
     23400  as Gl_Number,
        y.Plan as Description,
        0 as Hours,
        ROUND(SUM(Ee_Curr),2) as Debit,
        0 as Credit
    FROM "PR_YLOC" y
    LEFT JOIN PR_SUMM s ON (s.Summ_No = y.Summ_No)
    WHERE y.Loc_No = 1041
    AND s.Pay_Date =  2010-04-02 
    AND y.Code IN (100, 105, 110)
    AND y.Type = 3
    GROUP BY y.Plan
) UNION (
    SELECT 
     72000  as Gl_Number,
        y.Plan,
        0,
        ROUND(SUM(Er_Curr),2),
        0
    FROM "PR_YLOC" y
    LEFT JOIN PR_SUMM s ON (s.Summ_No = y.Summ_No)
    WHERE y.Loc_No = 1041
    AND s.Pay_Date =  2010-04-02 
    AND y.Code IN (100, 105, 110)
    AND y.Type = 3
    GROUP BY y.Plan
) UNION (
SELECT  24800 ,
       c.Plan,
       0,
       ROUND(SUM(Ee_Amt),2),
       0
    FROM "PR_CDED" c WHERE Pay_Date =  2010-04-02  AND Loc_No = 1041 AND Code = 100
    GROUP BY c.Plan
) UNION (
SELECT  24800 ,
       c.Plan,
       0,
       0,
       ROUND(SUM(Ee_Amt),2)
    FROM "PR_CDED" c WHERE Pay_Date =  2010-04-02  AND Loc_No = 1041 AND Code = 115
    GROUP BY c.Plan
) UNION (
SELECT  24150 ,
       c.Plan,
       0,
       0,
       ROUND(SUM(Ee_Amt),2)    
    FROM "PR_CDED" c WHERE Pay_Date =  2010-04-02  AND Loc_No = 1041 AND Code = 241
    GROUP BY c.Plan
) UNION (
SELECT  24150 ,
       c.Plan,
       0,
       ROUND(SUM(Ee_Amt),2),
       0
    FROM "PR_CDED" c WHERE Pay_Date =  2010-04-02  AND Loc_No = 1041 AND Code = 239
    GROUP BY c.Plan
) UNION (
SELECT  24120 ,
       c.Plan,
       0,
       ROUND(SUM(Ee_Amt),2),
       0
    FROM "PR_CDED" c WHERE Pay_Date =  2010-04-02  AND Loc_No = 1041 AND Code = 230
    GROUP BY c.Plan
) UNION (
SELECT  24100 ,
       c.Plan,
       0,
       ROUND(SUM(Ee_Amt),2),
       0
    FROM "PR_CDED" c WHERE Pay_Date =  2010-04-02  AND Loc_No = 1041 AND Code = 225
    GROUP BY c.Plan
) UNION (
SELECT  23800 ,
       c.Plan,
       0,
       ROUND(SUM(Ee_Amt),2),
       0
    FROM "PR_CDED" c WHERE Pay_Date =  2010-04-02  AND Loc_No = 1041 AND Code = 245
    GROUP BY c.Plan
) UNION (
select m.Def_Dept as Gl_Number, t.Short_Desc,
    (SELECT SUM(Hours) FROM pr_earn en WHERE en.Loc_No = e.Loc_No AND en.Emp_No = e.Emp_No AND en.Pay_Date = e.Pay_Date AND en.Pay_Code = e.Pay_Code) as Hours,
    (SELECT SUM(Pay_Amt) FROM pr_earn en WHERE en.Loc_No = e.Loc_No AND en.Emp_No = e.Emp_No AND en.Pay_Date = e.Pay_Date AND en.Pay_Code = e.Pay_Code) as Debit,
    0
from pr_earn e
left join pr_mast m on (e.Loc_No = m.Loc_No and e.Emp_No = m.Emp_No)
left join pr_ptype t ON (t.Code = e.Pay_Code)
where e.loc_no = 1041 and e.pay_date =  2010-04-02 
group by m.Def_Dept, t.Short_Desc
)

Thanks

问题回答

Could you replace the middle set of SELECT statements with something like this?

) UNION (
SELECT CASE Code
         WHEN 100 THEN  24800 
         WHEN 115 THEN  24800 ,
         WHEN 241 THEN  24150 
         WHEN 239 THEN  24150 ,
         WHEN 230 THEN  24120 ,
         WHEN 225 THEN  24100 
         WHEN 245 THEN  23800 ,
       END,
       c.Plan,
       0,
       ROUND(SUM(Ee_Amt),2),
       0
    FROM "PR_CDED" c WHERE Pay_Date =  2010-04-02  AND Loc_No = 1041 AND Code IN (100, 115, 241, 239, 230, 225, 245)
    GROUP BY c.Plan
) UNION (

That s a T-SQL CASE statement, but I m sure Oracle PL/SQL has something similar.

Instead of many selects with almost the same filter criteria (difference at "AND Code = ..."), you could replace with only one select with filter criteria AND Code IN (..., ..., ...).

Seems like you re trying to have more maintainability without affecting performance. I don t know this platform, but I would guess that you could move one where clause to the end, with your Unions as a subquery, and that the query optimzer might be able to figure out to apply the where conditions in each unioned set.

You can use a case statement for this. E.g.:

SELECT  
 23400  as Gl_Number, 
    y.Plan as Description, 
    0 as Hours, 
    ROUND(SUM(Ee_Curr),2) as Debit, 
    0 as Credit 
FROM "PR_YLOC" y 
LEFT JOIN PR_SUMM s ON (s.Summ_No = y.Summ_No) 
WHERE y.Loc_No = 1041 
AND s.Pay_Date =  2010-04-02  
AND y.Code IN (100, 105, 110) 
AND y.Type = 3 
GROUP BY y.Plan 
UNION
SELECT  
 72000  as Gl_Number, 
    y.Plan, 
    0, 
    ROUND(SUM(Er_Curr),2), 
    0 
FROM "PR_YLOC" y 
LEFT JOIN PR_SUMM s ON (s.Summ_No = y.Summ_No) 
WHERE y.Loc_No = 1041 
AND s.Pay_Date =  2010-04-02  
AND y.Code IN (100, 105, 110) 
AND y.Type = 3 
GROUP BY y.Plan 
UNION
SELECT case Code 
            when Code in (100,115) then 24800 
            when Code in (241, 239) then 24150 
            when Code = 230 then 24120 
            when Code = 225 then 24100 
            when Code = 245 then 23800 
        end, 
       c.Plan, 
       0, 
       ROUND(SUM(Ee_Amt),2), 
       0 
    FROM "PR_CDED" c WHERE Pay_Date =  2010-04-02  AND Loc_No = 1041 AND Code in (100,115,241,239,230,225,245)
    GROUP BY c.Plan 
select m.Def_Dept as Gl_Number, t.Short_Desc, 
    (SELECT SUM(Hours) FROM pr_earn en WHERE en.Loc_No = e.Loc_No AND en.Emp_No = e.Emp_No AND en.Pay_Date = e.Pay_Date AND en.Pay_Code = e.Pay_Code) as Hours, 
    (SELECT SUM(Pay_Amt) FROM pr_earn en WHERE en.Loc_No = e.Loc_No AND en.Emp_No = e.Emp_No AND en.Pay_Date = e.Pay_Date AND en.Pay_Code = e.Pay_Code) as Debit, 
    0 
from pr_earn e 
left join pr_mast m on (e.Loc_No = m.Loc_No and e.Emp_No = m.Emp_No) 
left join pr_ptype t ON (t.Code = e.Pay_Code) 
where e.loc_no = 1041 and e.pay_date =  2010-04-02  
group by m.Def_Dept, t.Short_Desc 




相关问题
摘录数据

我如何将Excel板的数据输入我的Django应用? I m将PosgreSQL数据库作为数据库。

Postgres dump of only parts of tables for a dev snapshot

On production our database is a few hundred gigabytes in size. For development and testing, we need to create snapshots of this database that are functionally equivalent, but which are only 10 or 20 ...

How to join attributes in sql select statement?

I want to join few attributes in select statement as one for example select id, (name + + surname + + age) as info from users this doesn t work, how to do it? I m using postgreSQL.

What text encoding to use?

I need to setup my PostgreSQL DB s text encoding to handle non-American English characters that you d find showing up in languages such as German, Spanish, and French. What character encoding should ...

SQL LIKE condition to check for integer?

I am using a set of SQL LIKE conditions to go through the alphabet and list all items beginning with the appropriate letter, e.g. to get all books where the title starts with the letter "A": SELECT * ...

热门标签