Retrieving specific column data from SQL sub-query - sql

My goal is to pull out the values shown in red in the picture.
I used this query to pull the data together. The rows are associated via ActionID and filtered with the 'AND' conditions shown.
SELECT [lclTime],[Descript],[Event],[PValue],[Phase],[ActionID]
FROM TableA
WHERE uniqueid = 5742
AND ActionID <> 0
AND LEN(Phase) = 0
AND [ActionID] in
(
SELECT [ActionID] FROM TableA
WHERE uniqueid = 5742
AND ActionID <> 0
AND LEN(Phase) = 0
GROUP BY [ActionID]
HAVING COUNT(*) > 2
)
I thought I could treat the output from above, as the input to another query, to allow me to choose the values I need to extract. But was unsuccesful.
I also thought that maybe PIVOT could be used to pull out the values in the columns... but I need values from multiple columns and couldn't get that syntax to even work.
Can this be done without temp tables? I don't think the 3rd party app, that will execute this code, plays nicely with temp tables.
Thanks in advance.
UPDATE: I should have clarified what I'm trying to achieve for a result set. For each set described by the subquery, I'm trying to extract a single record per unique ActionID. And the values with the ActionID would include the value of lclTime, Descript and Pvalue when Event=Successful Signoff, and the value of PValue when Event=State Command.

I suspect that you want conditional aggregation, to bring the values of events "State Command" and "Successful Signoff" for each actionid that satisfies the filter conditions and that have at least 3 occurences.
If so, you can use a window count for filtering, and then conditional aggregation to pivot:
select actionid,
max(case when event = 'State Command' then pvalue end) command_value,
max(case when event = 'State Command' then lcltime end) command_lcltime,
max(case when event = 'Successful Signoff' then pvalue end) signoff_value,
max(case when event = 'Successful Signoff' then lcltime end) signoff_lcltime,
from (
select a.*, count(*) over(partition by actionid) cnt
from tablea
where uniqueid = 5742 and actionid <> 0 and len(phase) = 0
) t
where cnt > 2
group by actionid

Related

How do I pull row values based on category into separate columns in teradata sql?

I tried doing aggregation but it still results in multiple rows for each id. I would like to write a query to get data as in result table (2nd) from the source table (1). AmtCategory 1->AmtPaid, 2-AmtReturned, 3->Fees
You can use conditional aggregation to pivot the dataset like so:
select userid,
coalesce(max(case when amtcategory = 1 then amttransac end), 0) amtpaid,
coalesce(max(case when amtcategory = 2 then amttransac end), 0) amtreturned,
coalesce(max(case when amtcategory = 3 then amttransac end), 0€ fees
from mytable
group by userid

BigQuery(standard SQL) grouping values based on first CASE WHEN statement

Here is my query with the output below the syntax.
SELECT DISTINCT CASE WHEN id = 'RUS0261431' THEN value END AS sr_type,
COUNT(CASE WHEN id in ('RUS0290788') AND value in ('1','2','3','4') THEN respondentid END) AS sub_ces,
COUNT(CASE WHEN id IN ('RUS0290788') AND value in ('5','6','7') THEN respondentid END) AS pos_ces,
COUNT(*) as total_ces
FROM `some_table`
WHERE id in ( 'RUS0261431') AND id <> '' AND value IS NOT NULL
GROUP BY 1
As you can see with the attached table I'm unable to group the values based on Id RUS0290788 with the distinct values that map to RUS0261431. Is there anyway to pivot with altering my case when statements so I can group sub_ces and pos_ces by sr_type. Thanks in advanceenter image description here
You can simplify your WHERE condition to WHERE id = ('RUS0261431'). Only records with this value will be selected so you do not have to repeat this in the CASE statements.

selecting details from the table based on the where condition on same column with different filtering option

I am having a table with below specified structure
From the table, I just want to retrieve the product id which is having Ram with value 12 and color with Blue. The expected result is 1.
I tried many queries and it's not sharing the expected result.
What will be the solution?
It's very difficult to manage the separate table for each feature as we have an undefined set of features.
You can use conditional aggregation:
select productid
from t
group by productid
having max(case when feature = 'Ram' then value end) = '12' and
max(case when feature = 'Color' then value end) = 'Blue';
use correlated subquery with not exists
select distinct product_id from tablename a
where not exists
(select 1 from tablename b where a.product_id=b.product_id and feature='Ram' and value<>12)
and not exists
(select 1 from tablename c where a.product_id=c.product_id and feature='Color' and value<>'blue')

pivot table returns more than 1 row for the same ID

I have a sql code which I am using to do pivot. Code is as follows:
SELECT DISTINCT PersonID
,MAX(pivotColumn1)
,MAX(pivotColumn2) --originally these were in 2 separate rows)
FROM(SELECT srcID, PersonID, detailCode, detailValue) FROM src) AS SrcTbl
PIVOT(MAX(detailValue) FOR detailCode IN ([pivotColumn1],[pivotColumn2])) pvt
GROUP BY PersonID
In the source data the ID has 2 separate rows due to having its own ID which separates the values. I have now pivoted it and its still giving me 2 separate rows for the ID even though i grouped it and used aggregation on the pivot columns. Ay idea whats wrong with the code?
So I have all my possible detailCode listed in the IN clause. So I have null returned when the value is none but I want it all summarised in 1 row. See image below.
If those are all the options of detailCode , you can use conditional aggregation with CASE EXPRESSION instead of Pivot:
SELECT t.personID,
MAX(CASE WHEN t.detailCode = 'cas' then t.detailValue END) as cas,
MAX(CASE WHEN t.detailCode = 'buy' then t.detailValue END) as buy,
MAX(CASE WHEN t.detailCode = 'sel' then t.detailValue END) as sel,
MAX(CASE WHEN t.detailCode = 'pla' then t.detailValue END) as pla
FROM YourTable t
GROUP BY t.personID

How do I determine if a group of data exists in a table, given the data that should appear in the group's rows?

I am writing data to a table and allocating a "group-id" for each batch of data that is written. To illustrate, consider the following table.
GroupId Value
------- -----
1 a
1 b
1 c
2 a
2 b
3 a
3 b
3 c
3 d
In this example, there are three groups of data, each with similar but varying values.
How do I query this table to find a group that contains a given set of values? For instance, if I query for (a,b,c) the result should be group 1. Similarly, a query for (b,a) should result in group 2, and a query for (a, b, c, e) should result in the empty set.
I can write a stored procedure that performs the following steps:
select distinct GroupId from Groups -- and store locally
for each distinct GroupId: perform a set-difference (except) between the input and table values (for the group), and vice versa
return the GroupId if both set-difference operations produced empty sets
This seems a bit excessive, and I hoping to leverage some other commands in SQL to simplify. Is there a simpler way to perform a set-comparison in this context, or to select the group ID that contains the exact input values for the query?
This is a set-within-sets query. I like to solve it using group by and having:
select groupid
from GroupValues gv
group by groupid
having sum(case when value = 'a' then 1 else 0 end) > 0 and
sum(case when value = 'b' then 1 else 0 end) > 0 and
sum(case when value = 'c' then 1 else 0 end) > 0 and
sum(case when value not in ('a', 'b', 'c') then 1 else - end) = 0;
The first three conditions in the having clause check that each elements exists. The last condition checks that there are no other values. This method is quite flexible, for various exclusions and inclusion conditions on the values you are looking for.
EDIT:
If you want to pass in a list, you can use:
with thelist as (
select 'a' as value union all
select 'b' union all
select 'c'
)
select groupid
from GroupValues gv left outer join
thelist
on gv.value = thelist.value
group by groupid
having count(distinct gv.value) = (select count(*) from thelist) and
count(distinct (case when gv.value = thelist.value then gv.value end)) = count(distinct gv.value);
Here the having clause counts the number of matching values and makes sure that this is the same size as the list.
EDIT:
query compile failed because missing the table alias. updated with right table alias.
This is kind of ugly, but it works. On larger datasets I'm not sure what performance would look like, but the nested instances of #GroupValues key off GroupID in the main table so I think as long as you have a good index on GroupID it probably wouldn't be too horrible.
If Object_ID('tempdb..#GroupValues') Is Not Null Drop Table #GroupValues
Create Table #GroupValues (GroupID Int, Val Varchar(10));
Insert #GroupValues (GroupID, Val)
Values (1,'a'),(1,'b'),(1,'c'),(2,'a'),(2,'b'),(3,'a'),(3,'b'),(3,'c'),(3,'d');
If Object_ID('tempdb..#FindValues') Is Not Null Drop Table #FindValues
Create Table #FindValues (Val Varchar(10));
Insert #FindValues (Val)
Values ('a'),('b'),('c');
Select Distinct gv.GroupID
From (Select Distinct GroupID
From #GroupValues) gv
Where Not Exists (Select 1
From #FindValues fv2
Where Not Exists (Select 1
From #GroupValues gv2
Where gv.GroupID = gv2.GroupID
And fv2.Val = gv2.Val))
And Not Exists (Select 1
From #GroupValues gv3
Where gv3.GroupID = gv.GroupID
And Not Exists (Select 1
From #FindValues fv3
Where gv3.Val = fv3.Val))