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>
Related
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
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.
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]
i guess i just lack the keywords to search, but this is burning on my mind:
how can i add a condition to the sum-function in the select-statement like
select sum(a), sum(b where c=1) from db;?
this means, i want to see the sum of column a and the sum of column b, but only of the records in column b of which column c has the value 1.
the output of heidi just says "bad syntac near WHERE". may there be any other way?
thanks in advance and best regards from Berlin, joachim
The exact syntax may differ depending on the database engine, however it will be along the lines of
SELECT
sum(a),
sum(CASE WHEN c = 1 THEN b ELSE 0 END)
FROM
db
select sum(case when c=1 then b else 0 end)
This technique is useful when you need a lot of aggregates on the same set of data - you can query the entire table without applying a where filter, and have a bunch of these which give you aggregated data for a specific filter.
It's also useful when you need a lot of counts based on filters - you can do sums of 1 or 0:
select sum(case when {somecondition} then 1 else 0 end)
I've got a table called datapoints with about 150 columns and 2600 rows. I know, 150 columns is too much, but I got this db after importing a csv and it is not possible to shrink the number of columns.
I have to get some statistical stuff out of the data. E.g. one question would be:
Give me the total number of fields (of all columns), which are null. Does somebody have any idea how I can do this efficiently?
For one column it isn't a problem:
SELECT count(*) FROM datapoints tb1 where 'tb1'.'column1' is null;
But how can I solve this for all columns together, without doing it by hand for every column?
Best,
Michael
Building on Lamak's idea, how about this idea:
SELECT (N * COUNT(*)) - (
COUNT(COLUMN_1)
+ COUNT(COLUMN_2)
+ ...
+ COUNT(COLUMN_N)
)
FROM DATAPOINTS;
where N is the number of columns. The trick will be in making the summation series of COUNT(column), but that shouldn't be too terrible with a good text editor and/or spreadsheet.
i don't think there is an easy way to do it. i'd get started on the 150 queries. you only have to replace one word (column name) each time.
Well, COUNT (and most aggregations funcions) ignore NULL values. In your case, since you are using COUNT(*), it counts every row in the table, but you can do that on any column. Something like this:
SELECT TotalRows-Column1NotNullCount, etc
FROM (
SELECT COUNT(1) TotalRows,
COUNT(column1) Column1NotNullCount,
COUNT(column2) Column2NotNullCount,
COUNT(column3) Column3NotNullCount ....
FROM datapoints) A
To get started it's often helpful to use a visual query tool to generate a field list and then use cut/paste/search/replace or manipulation in a spreadsheet program to transform it into what is needed. To do it all in one step you can use something like:
SELECT SUM(CASE COLUMN1 WHEN NULL THEN 1 ELSE 0 END) +
SUM(CASE COLUMN2 WHEN NULL THEN 1 ELSE 0 END) +
SUM(CASE COLUMN3 WHEN NULL THEN 1 ELSE 0 END) +
...
FROM DATAPOINTS;
With a visual query builder you can quickly generate:
SELECT COLUMN1, COLUMN2, COLUMN3 ... FROM DATAPOINTS;
You can then replace the comma with all the text that needs to appear between two field names followed by fixing up the first and last fields. So in the example search for "," and replace with " WHEN NULL 1 ELSE 0 END) + SUM(CASE " and then fix up the first and last fields.