How to optimise below sql query - sql

I have a backend limitation that the Resultant column which is of decimal type(aban) can not have more than 1000 characters in it formula.
How to optimise this query?
I have tried using tempTable but results are not as expected.
aban =
CASE
WHEN (
sum(isnull(a.callshandled,0)) + sum(isnull(a.totalcallsaband,0)) + sum(isnull(a.incompletecalls,0)) + sum(isnull(a.returnbusy,0)) + sum(isnull(a.returnring,0)) + sum(isnull(a.icrdefaultrouted,0)) + sum(isnull(a.ndr,0)) + sum(isnull(a.overflowout,0)) + sum(isnull(a.callsrona,0)) + sum(isnull(a.returnrelease,0)) + sum(isnull(a.callsroutednonagent,0)) + sum(isnull(a.shortcalls,0)) + sum(isnull(a.agenterrorcount,0)) + sum(isnull(a.errorcount,0))
)
= 0 THEN
0
ELSE (sum(isnull(a.totalcallsaband,0)) * 1.0) / (sum(isnull(a.callshandled,0)) + sum(isnull(a.totalcallsaband,0)) + sum(isnull(a.incompletecalls,0)) + sum(isnull(a.returnbusy,0)) + sum(isnull(a.returnring,0)) + sum(isnull(a.icrdefaultrouted,0)) + sum(isnull(a.networkdefaultrouted,0)) + sum(isnull(a.overflowout,0)) + sum(isnull(a.callsrona,0)) + sum(isnull(a.returnrelease,0)) + sum(isnull(a.callsroutednonagent,0)) + sum(isnull(a.shortcalls,0)) + sum(isnull(a.agenterrorcount,0)) + sum(isnull(a.errorcount,0)))
END
,
Optimise the query in such a way that number of characters in formula is less then 1000 and resultant column should have same value before and after query optimisation.

Please try this way:
DECLARE #dividend int = 10;
DECLARE #divisor int = 0;
SELECT COALESCE(#dividend / NULLIF(#divisor,0), 0);
So you can avoid duplicate calculation for divisor.

Related

How can I increase the time complexity of this algorithm in SQL Server

I am trying to generate the combinations of each possible team fitting the rules for a league. I have two different methods that I have approached. One is do everything in one single select.
Mind you there are probably about 16 qbs 32 rbs 104 wrs 32 te's 16 dsts 16 k's and then 168 fx's. After 10 hours I generated millions of items but it still hadn't worked its way through completely.
SELECT
QB.name, RB1.name, RB2.name, WR1.name, WR2.name, WR3.name, TE.name, FX.name, K.name, DST.name,
(QB.salary + RB1.salary + RB2.salary + WR1.salary + WR2.salary + WR3.salary + TE.salary + FX.salary + K.salary + DST.salary) AS cost,
(QB.projectedFloor + RB1.projectedFloor + RB2.projectedFloor + WR1.projectedFloor + WR2.projectedFloor + WR3.projectedFloor + TE.projectedFloor + FX.projectedFloor + K.projectedFloor + DST.projectedFloor) AS lowest,
(QB.projectedCeiling + RB1.projectedCeiling + RB2.projectedCeiling + WR1.projectedCeiling + WR2.projectedCeiling + WR3.projectedCeiling + TE.projectedCeiling + FX.projectedCeiling + K.projectedCeiling + DST.projectedCeiling) AS highest,
(QB.projectedPoints + RB1.projectedPoints + RB2.projectedPoints + WR1.projectedPoints + WR2.projectedPoints + WR3.projectedPoints + TE.projectedPoints + FX.projectedPoints + K.projectedPoints + DST.projectedPoints) AS projection
FROM quarterbacks QB
INNER JOIN defense DST
ON DST.defenseId = DST.defenseId
INNER JOIN kicker K
ON K.kickerId = K.kickerId
INNER JOIN tightends TE
ON TE.playersId = TE.playersId
INNER JOIN runningbacks RB1
ON RB1.playersId = RB1.playersId
INNER JOIN runningbacks RB2
ON RB2.playersId = RB2.playersId
INNER JOIN receivers WR1
ON WR1.playersId = WR1.playersId
INNER JOIN receivers WR2
ON WR2.playersId = WR2.playersId
INNER JOIN receivers WR3
ON WR3.playersId = WR3.playersId
INNER JOIN flex FX
ON FX.playersId = FX.playersId
WHERE
RB1.runningbacksId != RB2.runningbacksId AND
WR1.receiversId != WR2.receiversId AND
WR1.receiversId != WR3.receiversId AND
WR2.receiversId != WR3.receiversId AND
FX.playersId != RB1.playersId AND
FX.playersId != RB2.playersId AND
FX.playersId != WR1.playersId AND
FX.playersId != WR2.playersId AND
FX.playersId != WR3.playersId AND
FX.playersId != TE.playersId AND
(QB.salary + RB1.salary + RB2.salary + WR1.salary + WR2.salary + WR3.salary + TE.salary + K.salary + DST.salary) < 50000 AND
(QB.salary + RB1.salary + RB2.salary + WR1.salary + WR2.salary + WR3.salary + TE.salary + K.salary + DST.salary) > 45000
AND
(QB.projectedPoints + RB1.projectedPoints + RB2.projectedPoints + WR1.projectedPoints + WR2.projectedPoints + WR3.projectedPoints + TE.projectedPoints + FX.projectedPoints + K.projectedPoints + DST.projectedPoints) > 100
ORDER BY
(QB.projectedCeiling + RB1.projectedCeiling + RB2.projectedCeiling + WR1.projectedCeiling + WR2.projectedCeiling + WR3.projectedCeiling + TE.projectedCeiling + FX.projectedCeiling + K.projectedCeiling + DST.projectedCeiling),
(QB.projectedPoints + RB1.projectedPoints + RB2.projectedPoints + WR1.projectedPoints + WR2.projectedPoints + WR3.projectedPoints + TE.projectedPoints + FX.projectedPoints + K.projectedPoints + DST.projectedPoints),
(QB.projectedFloor + RB1.projectedFloor + RB2.projectedFloor + WR1.projectedFloor + WR2.projectedFloor + WR3.projectedFloor + TE.projectedFloor + FX.projectedFloor + K.projectedFloor + DST.projectedFloor)
I also have another approach in which I may not be understanding clearly if it would be faster. It involves making smaller tables and then joining them together.
DECLARE #QBSRBS TABLE (
qb nvarchar(max),
rb1 nvarchar (max),
rb2 nvarchar (max),
cost int,
highest float,
lowest float,
points float
);
DECLARE #WRS TABLE (
wr1 nvarchar(max),
wr2 nvarchar(max),
wr3 nvarchar(max),
cost int,
highest float,
lowest float,
points float
);
DECLARE #TEsDSTK TABLE (
te nvarchar(max),
fx nvarchar(max),
dst nvarchar(max),
k nvarchar(max),
cost int,
highest float,
lowest float,
points float
);
INSERT INTO #QBSRBS
SELECT
QB.name, RB1.name, RB2.name,
(QB.salary + RB1.salary + RB2.salary ) AS cost,
(QB.projectedFloor + RB1.projectedFloor + RB2.projectedFloor) AS lowest,
(QB.projectedCeiling + RB1.projectedCeiling + RB2.projectedCeiling) AS highest,
(QB.projectedPoints + RB1.projectedPoints + RB2.projectedPoints) AS projection
FROM quarterbacks QB
INNER JOIN runningbacks RB1
ON RB1.playersId = RB1.playersId
INNER JOIN runningbacks RB2
ON RB2.playersId = RB2.playersId
WHERE
RB1.runningbacksId != RB2.runningbacksId AND
RB1.team != RB2.team
INSERT INTO #WRS
SELECT
WR1.name, WR2.name, WR3.name,
(WR1.salary + WR2.salary + WR3.salary) AS cost,
(WR1.projectedFloor + WR2.projectedFloor + WR3.projectedFloor) AS lowest,
(WR1.projectedCeiling + WR2.projectedCeiling + WR3.projectedCeiling) AS highest,
(WR1.projectedPoints + WR2.projectedPoints + WR3.projectedPoints) AS projection
FROM receivers WR1
INNER JOIN receivers WR2
ON WR2.playersId = WR2.playersId
INNER JOIN receivers WR3
ON WR3.playersId = WR3.playersId
WHERE WR1.receiversId != WR2.receiversId AND
WR1.receiversId != WR3.receiversId AND
WR2.receiversId != WR3.receiversId AND
WR1.team != WR2.team AND WR1.team != WR3.team AND
WR2.team != WR3.team
INSERT INTO #TEsDSTK
SELECT TE.name, FX.name, K.name, DST.name,
(TE.salary + FX.salary + K.salary + DST.salary) AS cost,
(TE.projectedFloor + FX.projectedFloor + K.projectedFloor + DST.projectedFloor) AS lowest,
(TE.projectedCeiling + FX.projectedCeiling + K.projectedCeiling + DST.projectedCeiling) AS highest,
(TE.projectedPoints + FX.projectedPoints + K.projectedPoints + DST.projectedPoints) AS projection
FROM kicker K
INNER JOIN tightends TE
ON TE.playersId = TE.playersId
INNER JOIN flex FX
ON FX.playersId = FX.playersId
INNER JOIN defense DST
ON DST.defenseId = DST.defenseId
WHERE TE.playersId != FX.playersId
SELECT
qb, rb1, rb2, wr1, wr2, wr3, te, fx, k, dst,
(QR.cost + WR.cost + TFDK.cost) as cost,
(QR.lowest + WR.lowest + TFDK.lowest ) as lowest,
(QR.highest + WR.highest + TFDK.highest) as highest,
(QR.points + WR.points + TFDK.points) as points
FROM #QBSRBS QR
INNER JOIN #TEsDSTK TFDK
ON TFDK.cost = TFDK.cost
INNER JOIN #WRS WR
ON WR.cost = WR.cost
WHERE
QR.rb1 != TFDK.fx AND
QR.rb2 != TFDK.fx AND
WR.wr1 != TFDK.fx AND
WR.wr2 != TFDK.fx AND
WR.wr3 != TFDK.fx AND
(QR.highest + WR.highest + TFDK.highest) > 203
How can I improve the efficiency of this?

SQL select, sum and group

I'm struggling with an Access database:
I have a large database with the headers TAG, ZST, KL and R1H00 to R1H23 (24 of them, each one stands for one hour of a day) and I need to get a specific dataset out of it:
SELECT TAG, ZST, (R1H00 + R1H01 + R1H02 + R1H03 + R1H04 + R1H05 + R1H06 + R1H07 + R1H08 + R1H09 + R1H10 + R1H11 + R1H12 + R1H13 + R1H14 + R1H15 + R1H16 + R1H17 + R1H18 + R1H19 + R1H20 + R1H21 + R1H22 + R1H23) AS TOTAL
FROM Klassendaten
WHERE KL = "SWISS7_PW"
So far so good, but the result contains many items with the same ID (ZST). I need to sum all entries with the same ZST, but I couldn't manage to do it so far. (I tried to use the GROUP BY statement, but that only results in errors)
Any experienced SQL people here that could help me with this?
use group by
SELECT TAG, ZST, sum(R1H00 + R1H01 + R1H02 + R1H03 + R1H04 + R1H05 + R1H06 + R1H07 + R1H08 + R1H09 + R1H10 + R1H11 + R1H12 + R1H13 + R1H14 + R1H15 + R1H16 + R1H17 + R1H18 + R1H19 + R1H20 + R1H21 + R1H22 + R1H23) AS TOTAL
FROM Klassendaten
WHERE KL = "SWISS7_PW"
GROUP BY TAG, ZST;
Use the Sum() function
SELECT TAG, ZST, Sum(R1H00 + R1H01 + R1H02 + R1H03 + R1H04 + R1H05 + R1H06 + R1H07 + R1H08 + R1H09 + R1H10 + R1H11 + R1H12 + R1H13 + R1H14 + R1H15 + R1H16 + R1H17 + R1H18 + R1H19 + R1H20 + R1H21 + R1H22 + R1H23) AS TOTAL
FROM Klassendaten
where ZST = '(Whatever it is)'
group by tag, zst

Eliminating multiple delimiters in single column in oracle

My table has single column info
Info
+aname + + + + + + +ano+ + + + + + + + + +agender+ + + + + + + + + + + + +arace
I should get output like
aname+ano+agender+arace
I have to eliminate multiple delimiters and replace with single +
I tried with regexp_replace and trim and working as below
select trim(REGEXP_REPLACE('+aname + + + + + + +
+ano + + + + + + + +
+agender+ + + + + + + + + + +
+arace', '\ + + ', '+'),'+') from dual;
i get output as
aname+++++++ano+++++++agender++++++++++arace
This regexp does the trick: '\++'
select REGEXP_REPLACE('+aname++++++ano+++++++++agender++++++++++++arace', '\++', '+') from dual;
To get rid of the leading + (like in your example), use ltrim (or trim to remove trailing + too).
select ltrim(REGEXP_REPLACE('+aname++++++ano+++++++++agender++++++++++++arace', '\++', '+'),'+') from dual;

IF THEN Statement in SQL to OpenEdge

I'm struggeling with an if statement towards an OpenEdge database via ODBC. The query I have works like a charm, but Progress wants me to define the if statement different and I have no clue. Is there anyone who can define the correct query for me?
IF
{Crediteur code|type=string} = 'HOEFASTE'
BEGIN
(SELECT
inok."vest-kd-arvo"+RTRIM('-') + RIGHT(CAST((inok."inok-nr" + 1000000) AS varchar(7)),6) AS inokvalue
,RTRIM("leso-kd")+RTRIM('-')+inok."vest-kd-arvo"+RTRIM('-')+CAST("inok-nr"AS varchar(6)) AS inokdisplay
,RIGHT(CAST((inok."inok-nr") AS varchar(7)),6) + '-' + inok."vest-kd-arvo" + '-' + RTRIM("leso-kd") AS inoknr
,RTRIM("leso-kd") AS soortfact
FROM
PUB.inok
WHERE
inok."vcdc-nr" = {Administratie|type=int32}
AND inok."inss-kd" NOT IN ('H','G')
)
ELSE
(SELECT
inok."vest-kd-arvo"+RTRIM('-') + RIGHT(CAST((inok."inok-nr" + 1000000) AS varchar(7)),6) AS inokvalue
,RTRIM("leso-kd")+RTRIM('-')+inok."vest-kd-arvo"+RTRIM('-')+CAST("inok-nr"AS varchar(6)) AS inokdisplay
,RIGHT(CAST((inok."inok-nr") AS varchar(7)),6) + '-' + inok."vest-kd-arvo" + '-' + RTRIM("leso-kd") AS inoknr
,RTRIM("leso-kd") AS soortfact
FROM
PUB.inok
WHERE
inok."rela-kd-kre" = {Crediteur code|type=string}
AND inok."vcdc-nr" = {Administratie|type=int32}
AND inok."inss-kd" NOT IN ('H','G')
)
END
If I understand correctly, only your WHERE-clause is different, based on "Crediteur code".
You could move the IF inside of the WHERE-clause. That will leave you with a single SELECT-statement. Does this alternative work for you?
SELECT
inok."vest-kd-arvo"+RTRIM('-') + RIGHT(CAST((inok."inok-nr" + 1000000) AS varchar(7)),6) AS inokvalue
,RTRIM("leso-kd")+RTRIM('-')+inok."vest-kd-arvo"+RTRIM('-')+CAST("inok-nr"AS varchar(6)) AS inokdisplay
,RIGHT(CAST((inok."inok-nr") AS varchar(7)),6) + '-' + inok."vest-kd-arvo" + '-' + RTRIM("leso-kd") AS inoknr
,RTRIM("leso-kd") AS soortfact
FROM
PUB.inok
WHERE
inok."rela-kd-kre" = (CASE WHEN {Crediteur code|type=string} = 'HOEFASTE' THEN inok."rela-kd-kre" ELSE {Crediteur code|type=string} END)
AND inok."vcdc-nr" = {Administratie|type=int32}
AND inok."inss-kd" NOT IN ('H','G')

How can I use SUM() to sum my result array?

My current method to add the rows together is like so:
$totalxp = $row['Attackxp'] + $row['Defencexp'] + $row['Strengthxp'] + $row['Hitpointsxp'] + $row['Rangedxp'] + $row['Prayerxp'] + $row['Magicxp'] + $row['Cookingxp'] + $row['Woodcuttingxp'] + $row['Fletchingxp'] + $row['Fishingxp'] + $row['Firemakingxp'] + $row['Craftingxp'] + $row['Smithingxp'] + $row['Miningxp'] + $row['Herblorexp'] + $row['Agilityxp'] + $row['Thievingxp'] + $row['Slayerxp'] + $row['Farmingxp'] + $row['Runecraftxp'] + $row['Constructionxp'];
But then I saw SUM() and I tried this:
SELECT SUM(xp) FROM skills WHERE playerName='Undercover'
It works but I needed all the values of xp, so I tried adding %xp but it wont work.
How could I use the Sum() function to add all the rows up instead of straining PHP?
Aggregate functions (IE: SUM, MIN, MAX, COUNT, etc) don't work across columns--they work on the values for the specific column, based on the grouping (GROUP BY) and filteration (JOIN and/or WHERE clause).
To add up values across columns, you need to add them like you would for normal mathematical equations:
SELECT Attackxp + Defencexp + Strengthxp + Hitpointsxp + Rangedxp + Prayerxp + Magicxp + Cookingxp+ Woodcuttingxp + Fletchingxp + Fishingxp + Firemakingxp + Craftingxp + Smithingxp + Miningxp + Herblorexp + Agilityxp + Thievingxp + Slayerxp + Farmingxp + Runecraftxp + Constructionxp AS total_xp
FROM skills
WHERE playerName = 'Undercover'
If you have more than one record associated to a playername, then you can use an aggregate function:
SELECT SUM(Attackxp + Defencexp + Strengthxp + Hitpointsxp + Rangedxp + Prayerxp + Magicxp + Cookingxp+ Woodcuttingxp + Fletchingxp + Fishingxp + Firemakingxp + Craftingxp + Smithingxp + Miningxp + Herblorexp + Agilityxp + Thievingxp + Slayerxp + Farmingxp + Runecraftxp + Constructionxp) AS total_xp
FROM skills
WHERE playerName = 'Undercover'
That depend of the table data if each player is one entity (row) then is enaught to add columns:
SELECT Attackxp + Defencexp + Strengthxp + Hitpointsxp +Rangedxp + Prayerxp + Magicxp + Cookingxp + Woodcuttingxp + Fletchingxp + Fishingxp + Firemakingxp + Craftingxp + Smithingxp + Miningxp + Herblorexp + Agilityxp + Thievingxp + Slayerxp + Farmingxp + Runecraftxp + Constructionxp
As totalSkills FROM skills WHERE playerName = 'Undercover'
But is there more rows per player then You will need to sum also the rows
SELECT SUM(Attackxp + Defencexp + Strengthxp + Hitpointsxp +Rangedxp + Prayerxp + Magicxp + Cookingxp + Woodcuttingxp + Fletchingxp + Fishingxp + Firemakingxp + Craftingxp + Smithingxp + Miningxp + Herblorexp + Agilityxp + Thievingxp + Slayerxp + Farmingxp + Runecraftxp + Constructionxp)
As totalSkills FROM skills WHERE playerName = 'Undercover'
SELECT SUM(`Attackxp`) + SUM(`Defencexp`) + ... AS `total_sum`
FROM skills
WHERE playerName='Undercover'