Complex SQL query to combine rows - sql

I have 2 tables first is
Thread { code, itr_global,campaign, contact, start_time,duration}
segment {code,thread,start_time,duration,state}
There are multiple other joins but these 2 are major joins. 2 table are realted as thread.code=segment.thread.
In segment table there will be multiple rows for singl thread. I need to get values
campaign start_time duration waititme talk_time hold_time wrap_time
Where wait_time I can get as segment.state=7 & talke_time=segment.state=6 & wrap time as segment.state=8
I am not able to get all these values in single row as it will give me 3 diffrent rows for each record. How can I get all the values in single row as per above format.

You need some conditional aggregation SUM(CASE...) to get the result you want.
All this is based on my guesses about the structure and meaning of your tables, which you omitted from your question.
SELECT thread.code, thread.campaign,
SUM(segment.duration) duration,
SUM(CASE WHEN segment.state = 7 THEN segment.duration END) waittime,
SUM(CASE WHEN segment.state = 6 THEN segment.duration END) talk_time,
SUM(CASE WHEN segment.state = 8 THEN segment.duration END) wrap_time,
42 hold_time, -- you didn't say how to get hold_time
SUM(CASE WHEN segment.state = 8 THEN segment.duration END) wrap_time
FROM Thread
LEFT JOIN segment ON Thread.code = segment.thread
GROUP BY thread.code, thread.campaign

Related

Max match same numbers from each row

To generate 1mln rows of report with the below mentioned script is taking almost 2 days so, really appreciate if somebody could help me with different script which the report can be generated within 10-15mins please.
The requirement of the report is as following;
Table “cover” contains 5mln rows & 6 columns of data and likewise table “data” contains 500,000 rows and 6 columns.
So, each numbers of the rows in table cover has to go through table date and provide the maximum matches.
For instance, as mentioned on the below tables, there could be 3 matches in row #1, 2 matches in row #2 and 5 matches in row #3 so the script has to select the max selection which is 5 in row #3.
Sample table
UPDATE public.cover_sheet AS fc
SET maxmatch = (SELECT MAX(tmp.mtch)
FROM (
SELECT (SELECT CASE WHEN fc.a=drwo.a THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.b=drwo.b THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.c=drwo.c THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.d=drwo.d THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.e=drwo.e THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.f=drwo.f THEN 1 ELSE 0 END) AS mtch
FROM public.data AS drwo
) AS tmp)
WHERE fc.code>0;
SELECT *
FROM public.cover_sheet AS fc
WHERE fc.maxmatch>0;
As #a_horse_with_no_name mentioned in the comment to the question, your question is not clear...
Seems, you want to get the number of records which 6 fields from both tables are equal.
I'd suggest to:
reduce the number of select statements, then the speed of query execution will increase,
split your query into few smaller ones (good practice), to check your logic,
use join to get equal data, see: Visual Representation of SQL Joins
use subquery or cte to get result on which you'll be able to update table.
I think you want to get result as follow:
SELECT COUNT(*) mtch
FROM public.cover_sheet AS fc INNER JOIN public.data AS drwo ON
fc.a=drwo.a AND fc.b=drwo.b AND fc.c=drwo.c AND fc.d=drwo.d AND fc.e=drwo.e AND fc.f=drwo.f
If i'm not wrong and above query is correct, the time of execution of above query will reduce to about 1-2 minutes.
Finally, update query may look like:
WITH qry AS
(
-- proper select statement here
)
UPDATE public.cover_sheet AS fc
SET maxmatch = qry.<fieldname>
FROM qry
WHERE fc.code>0 AND fc.<key> = qry.<key>;
Note:
I do not see your data and i know nothing about its structure, relationships, etc. So, you have to change above query to your needs.

Loop Back to Same Table

Is there a way to combine these two queries into a single query - just one trip to the database?
Both queries hit the same table, but the first is looking for Total Active Circuits, while the second is looking for Total Circuits.
I am hoping to display results like this...
4/15, 12/34, 2/21 (where the first number is ActiveCircuits and the second number is TotalCircuits)
SELECT COUNT(CircuitID) AS ActiveCircuits
FROM Circuit
WHERE StateID = 5
AND Active = 1
SELECT COUNT(CircuitID) AS TotalCircuits
FROM Circuit
WHERE StateID = 5
Use conditional aggregation:
SELECT COUNT(*) AS TotalCircuits,
SUM(CASE WHEN Active = 1 THEN 1 ELSE 0 END) as ActiveCircuits
FROM Circuit
WHERE StateID = 5;
This assumes that CircuitId is never NULL, which seems quite reasonable in a table called Circuit.
You can use case when to have a 1 wherever it's active and then take the sum to get the total # of 1's or activecircuits.
SELECT COUNT(CIRCUITID) AS TOTALCIRCUITS,
SUM(CASE WHEN ACTIVE = 1 THEN 1 ELSE 0 END) AS ACTIVECIRCUITS
FROM CIRCUIT
WHERE STATEID = 5

Qualifying a column in a SQL select statement

I'm looking to generate a query that pulls from several tables. Most are rather straightforward and I can pull a value from a table directly but there is one table that is pivoted so that the value I want depends on the value in another column.
The table looks like the below:
ID Condition Value
1 Stage1 6
2 Stage2 9
3 Stage3 5
4 Stage4 2
So I'm looking to write a query that essentially "qualifies" the value I want by telling the table which condition.
An example of my SQL:
Select Attribute1, Stage1Value, Stage2Value, Stage3Value
From attribute, stage
where attribute = project1
So I can't just pull the "Value" column as it needs to know which stage in the query.
There are 30 columns I am trying to pull - of which 13 fall into this category. Thanks for any help you can provide.
So, you want conditional aggregation something :
select a.<col>,
sum(case when s.Condition = 'Stage1' then s.value else 0 end),
. . .
sum(case when s.Condition = 'Stage4' then s.value else 0 end)
from attribute a inner join
stage s
on s.<col> = a.<col>
group by a.<col>

Count where conditions are different

I've been trying to optimize one of my more bulky db views.
Presently, I'm just using sub-selects 5 times to get the count of the company ID's.
(Select count(id) from company table where prospecting.stage = 'qualify') as Qualify,
(Select count(id) from company table where prospecting.stage = 'targetted') as Targetted,
Each company goes through 5 stages, I simply want to count the amount of companies in each stage by company location in separate columns.
I'm trying to do this in one select, but I am getting a bit stuck.
SUM(COUNT(CASE WHEN prospecting.stage = 'Qualify' THEN '1' ELSE '0' END)) as [Qualified]
SUM(COUNT(CASE WHEN prospecting.stage = 'Targetted' THEN '1' ELSE '0' END)) as [Targetted]
So it ends up looking something along these lines:
Location | Stage: Qualify | Stage: Targetted | Stage 3 | Stage 4 | Stage 5 | Total
Cannot perform an aggregate function on an expression containing an aggregate or a subquery. -Makes sense.
So I need to count the Company.ID where the prospecting.stage = 'XYZ' into separate rows per stage.
Any advice? :(
Drop the count function and change the datatype from char to int in the case expressions. Your expressions should look like this:
SUM(CASE WHEN prospecting.stage = 'Qualify' THEN 1 ELSE 0 END) as [Qualified]

Change the value of a sum in sql

I'm doing a query to obtain the numbers of people for a Christmas dinner.
The people include the workers and their relatives. The relatives are stored in a different table.
Children and adults eat a different menu and we organize tables by families.
I'm already using this query
select worker_name,
count(*) as total_per_family,
SUM(CASE WHEN age < 18 THEN 1 ELSE 0 END) as children,
SUM(CASE WHEN age >= 18 THEN 1 ELSE 0 END) as adults
from
(
/*subquery*/
)
group by worker_name
order by worker_name;
This query returns the number of child and adults related to the worker and count gives me the total.
The problem is that I need to add the worker to the adults sum.
Is there a way to modify adults? Either setting its initial value to 1 or adding 1 after the sum is done but before the count is obtained.
Modifying your query to read
SUM(CASE WHEN AGE>=18 THEN 1 ELSE 0 END) + 1 as adults
would probably be a first approach. The aggregate SUM() would be computed first, with 1 added thereafter as your initial suggestion indicated.