Get count and details of each count details - sql

I have a table called 'A' and another table called 'B'.
Here in table A i keep all the master details and where B it keeps the status of field A like approved, rejected.
My need is i need a single query with output as
{
submitted_count: 5,
{[details of first app], [details of 2 app], [], [],[]},
rejected_count : 2,
{[details of first app],[details of second app]}
}
How would i achieve this ?

If you want to convert the result of the query to JSON you need to use the json_agg function.
select json_agg(t)
from (
Select
count(1) as total,
string_agg(tb.detail,',') as details
FROM A tb
inner join B tbb
on tb.id = tbB.id_A
where tbb.status = true
union
Select
count(1) as total,
string_agg(tb.detail,',') as details
FROM A tb
inner join B tbb
on tb.id = tbB.id_A
where tbb.status = false
) t;
The output is a little bit different:
[{"total":2,"details":"Bob,Logan"},{"total":3,"details":"Scott,Jean,Gambit"}]
There is an example here how to use it

Related

Optimizing SQL Cross Join that checks if any array value in other column

Let's say I have a table events with structure:
id
value_array
XXXX
[a,b,c,d]
...
...
I have a second table values_of_interest with structure:
value
x
y
z
a
I want to find id's that have any of the values found in values_of_interest. All else equal, what would be the most performant SQL to make this happen? (I am using BigQuery, but feel free to answer more generally)
My current thought is:
SELECT
DISTINCT e.id
FROM
events e, values_of_interest vi
WHERE
EXISTS(
SELECT
value
FROM
UNNEST(e.value_array) value
JOIN
vi ON vi.value = e.value
)
Few quick options for BigQuery Standard SQL
Option 1
select id
from `project.dataset.events`
where exists (
select 1
from `project.dataset.values_of_interest`
where value in unnest(value_array)
)
Option 2
select id
from `project.dataset.events` t
where (
select count(1)
from t.value_array as value
join `project.dataset.values_of_interest`
using(value)
) > 0
I would write this using exists and a join:
select e.id
from `project.dataset.events` e
where exists (select 1
from unnest(e.value_array) val join
`project.dataset.values_of_interest` voi
on val = voi.value
);

BigQuery: update a row with count of a subquery and inner join

I have following two tables:
Table 1: Students
name:string,
age:integer,
class:integer,
number_of_allowed_trips:integer
Table 2: Trips
allowed_age:integer,
trip_name:string,
class:integer
I'm trying to assign for each student number of allowed trips based on some conditions. My query is:
UPDATE
`mydataset.students` AS s
SET
s.number_of_allowed_trips=(
SELECT
COUNT(*)
FROM
`mydataset.trips` AS t
WHERE
t.r.class= 9)
FROM
`mydataset.trips` AS t
WHERE
r.name = 'Jack'
AND r.class = 9
AND w.class = r.class
But this query doesn't work. What am I doing false? How can I get this code worked?
UPDATE
`mydataset.students` AS s
SET
s.number_of_allowed_trips= (
SELECT
COUNT(*)
FROM
`mydataset.trips` AS t
WHERE
t.class = s.class
AND s.age= 9 )
WHERE
s.id=s.id
This works fine!

T-SQL cursor or if or case when

I have this table:
Table_NAME_A:
quotid itration QStatus
--------------------------------
5329 1 Assigned
5329 2 Inreview
5329 3 sold
4329 1 sold
4329 2 sold
3214 1 assigned
3214 2 Inreview
Result output should look like this:
quotid itration QStatus
------------------------------
5329 3 sold
4329 2 sold
3214 2 Inreview
T-SQL query, so basically I want the data within "sold" status if not there then "inreview" if not there then "assigned" and also at the same time if "sold" or "inreview" or "assigned" has multiple iteration then i want the highest "iteration".
Please help me, thanks in advance :)
This is a prioritization query. One way to do this is with successive comparisons in a union all:
select a.*
from table_a a
where quote_status = 'sold'
union all
select a.*
from table_a a
where quote_status = 'Inreview' and
not exists (select 1 from table_a a2 where a2.quoteid = a.quoteid and a2.quotestatus = 'sold')
union all
select a.*
from table_a a
where quote_status = 'assigned' and
not exists (select 1
from table_a a2
where a2.quoteid = a.quoteid and a2.quotestatus in ('sold', 'Inreview')
);
For performance on a larger set of data, you would want an index on table_a(quoteid, quotestatus).
You want neither cursors nor if/then for this. Instead, you'll use a series of self-joins to get these results. I'll also use a CTE to simplify getting the max iteration at each step:
with StatusIterations As
(
SELECT quotID, MAX(itration) Iteration, QStatus
FROM table_NAME_A
GROUP BY quotID, QStats
)
select q.quotID, coalesce(sold.Iteration,rev.Iteration,asngd.Iteration) Iteration,
coalesce(sold.QStatus, rev.QStatus, asngd.QStatus) QStatus
from
--initial pass for list of quotes, to ensure every quote is included in the results
(select distinct quotID from table_NAME_A) q
--one additional pass for each possible status
left join StatusIterations sold on sold.quotID = q.quotID and sold.QStatus = 'sold'
left join StatusIterations rev on rev.quotID = q.quotID and rev.QStatus = 'Inreview'
left join StatusIterations asngd on asngd.quotID = q.quotID and asngd.QStatus = 'assigned'
If you have a table that equates a status with a numeric value, you can further improve on this:
Table: Status
QStatus Sequence
'Sold' 3
'Inreview' 2
'Assigned' 1
And the code becomes:
select t.quotID, MAX(t.itration) itration, t.QStatus
from
(
select t.quotID, MAX(s.Sequence) As Sequence
from table_NAME_A t
inner join Status s on s.QStatus = t.QStatus
group by t.quotID
) seq
inner join Status s on s.Sequence = seq.Sequence
inner join table_NAME_A t on t.quotID = seq.quotID and t.QStatus = s.QStatus
group by t.quoteID, t.QStatus
The above may look like complicated at first, but it can be faster and it will scale easily beyond three statuses without changing the code.

PostgreSQL - how to query "result IN ALL OF"?

I am new to PostgreSQL and I have a problem with the following query:
WITH relevant_einsatz AS (
SELECT einsatz.fahrzeug,einsatz.mannschaft
FROM einsatz
INNER JOIN bergefahrzeug ON einsatz.fahrzeug = bergefahrzeug.id
),
relevant_mannschaften AS (
SELECT DISTINCT relevant_einsatz.mannschaft
FROM relevant_einsatz
WHERE relevant_einsatz.fahrzeug IN (SELECT id FROM bergefahrzeug)
)
SELECT mannschaft.id,mannschaft.rufname,person.id,person.nachname
FROM mannschaft,person,relevant_mannschaften WHERE mannschaft.leiter = person.id AND relevant_mannschaften.mannschaft=mannschaft.id;
This query is working basically - but in "relevant_mannschaften" I am currently selecting each mannschaft, which has been to an relevant_einsatz with at least 1 bergefahrzeug.
Instead of this, I want to select into "relevant_mannschaften" each mannschaft, which has been to an relevant_einsatz WITH EACH from bergefahrzeug.
Does anybody know how to formulate this change?
The information you provide is rather rudimentary. But tuning into my mentalist skills, going out on a limb, I would guess this untangled version of the query does the job much faster:
SELECT m.id, m.rufname, p.id, p.nachname
FROM person p
JOIN mannschaft m ON m.leiter = p.id
JOIN (
SELECT e.mannschaft
FROM einsatz e
JOIN bergefahrzeug b ON b.id = e.fahrzeug -- may be redundant
GROUP BY e.mannschaft
HAVING count(DISTINCT e.fahrzeug)
= (SELECT count(*) FROM bergefahrzeug)
) e ON e.mannschaft = m.id
Explain:
In the subquery e I count how many DISTINCT mountain-vehicles (bergfahrzeug) have been used by a team (mannschaft) in all their deployments (einsatz): count(DISTINCT e.fahrzeug)
If that number matches the count in table bergfahrzeug: (SELECT count(*) FROM bergefahrzeug) - the team qualifies according to your description.
The rest of the query just fetches details from matching rows in mannschaft and person.
You don't need this line at all, if there are no other vehicles in play than bergfahrzeuge:
JOIN bergefahrzeug b ON b.id = e.fahrzeug
Basically, this is a special application of relational division. A lot more on the topic under this related question:
How to filter SQL results in a has-many-through relation
Do not know how to explain it, but here is an example how I solved this problem, just in case somebody has the some question one day.
WITH dfz AS (
SELECT DISTINCT fahrzeug,mannschaft FROM einsatz WHERE einsatz.fahrzeug IN (SELECT id FROM bergefahrzeug)
), abc AS (
SELECT DISTINCT mannschaft FROM dfz
), einsatzmannschaften AS (
SELECT abc.mannschaft FROM abc WHERE (SELECT sum(dfz.fahrzeug) FROM dfz WHERE dfz.mannschaft = abc.mannschaft) = (SELECT sum(bergefahrzeug.id) FROM bergefahrzeug)
)
SELECT mannschaft.id,mannschaft.rufname,person.id,person.nachname
FROM mannschaft,person,einsatzmannschaften WHERE mannschaft.leiter = person.id AND einsatzmannschaften.mannschaft=mannschaft.id;

SQL - GROUPING, ID, NAME

I was wondering what the answer should be for 1c. on this website:
http://sqlzoo.net/6.htm
SELECT company
FROM route WHERE stop=4
GROUP BY name, ID
this obviously isn't working, the ID and name isn't showing up no matter what. What is missing here? Thanks.
SELECT stops.id, stops.name
FROM route
INNER JOIN stops on route.stop = stops.id
WHERE route.num = 4 AND route.company = 'LRT'
You need to join the tables as the data you want to return is in a different table to the one which filters the data.
This works and does not include any unnecessary table joins. A good rule of thumb is to use EXISTS to verify values in a table that you do not need the output for. Otherwise, you would use a JOIN
SELECT stops.id, stops.name
FROM stops
WHERE EXISTS
(
SELECT 1 FROM route
WHERE route.stop = stops.id AND num = '4' AND company = 'LRT'
)
select s.id, s.name
from stops s
inner join route r
on s.id = r.stop
where r.num= 4
AND r.company= 'LRT'
It gives you this error:
sql: Unknown column 'name' in 'group statement'
There is no name in route tabel.
The tables structure are:
stops(id, name)
route(num,company,pos, stop)
So the answer for this quiz is:
SELECT s.id, s.name
FROM route r, stops s
WHERE r.stop= s.id
and r.num = 4 AND r.company = 'LRT'