Selecting rows and filler (null data) - sql

I have a table that looks like this:
ReportID | TeamID | Inning | Runs
1 A 1 3
1 A 2 3
1 A 5 7
1 B 1 3
1 B 3 2
1 B 6 1
I need to select all of that data, plus null data for the missing innings. It also need to stop at the max Inning for both teams (i.e. teamB's highest inning is 6, so I would collect 6 rows for both teamA and teamB yielding 12 total rows.)
For a visual, I need the output of the query to look like this:
ReportID | TeamID | Inning | Runs
1 A 1 3
1 A 2 3
1 A 3 NULL
1 A 4 NULL
1 A 5 7
1 A 6 NULL
1 B 1 3
1 B 2 NULL
1 B 3 2
1 B 4 NULL
1 B 5 NULL
1 B 6 1
Is there anyway to do this with just a query? Modifying the original table to add the null values is not an option.

Self join to generate the permutations of reports and teams
Left self join to generate hits which might be nullable.
This is probably a lot more efficient if it's done outside of SQL
SELECT ins.ReportID, teams.TeamID, ins.inning, score.Runs
FROM games as ins
JOIN games AS teams
ON ins.ReportID = teams.ReportID
LEFT JOIN games AS score
ON ins.ReportID = score.ReportID
AND teams.TeamID = score.TeamID
AND ins.inning = score.inning
GROUP BY ins.ReportID, teams.TeamID, ins.inning;

Related

How to add a condition to count function in PostgreSQL

I have these tables Course, subscription,subscription_Course(A table that creates a relation between Course and subscription), and another with Student. I want to Select all the id_courses that have a subscription count higher than 1 but only want to count the subscriptions from different students. Example: If a Student Subscribes two times the same course I want to have a condition that enables the count function to not count more than one time in these cases
These are my tables:
Student:
idStudent(pk)
cc
nif
1
30348507
232928185
2
30338507
231428185
3
30438507
233528185
4
30323231
3232132
Subscription
idsubscription(pk)
Student(fk)
value_subscription
vouchercurso
date
1
1
100
null
2021-11-01
2
2
150
null
2021-12-11
3
3
160
null
2021-01-03
4
4
500
null
1996-11-07
5
1
900
null
2001-07-05
6
2
432
null
2021-05-09
Subscription_Course
idsubscription(PK/fk)
id_Course(pk/fk)
Grade
1
3
9
2
4
15
3
5
12
6
3
9
5
4
16
2
6
20
6
5
4
For example, when counting within my table Subscription_Course only the id_course:5 would have a count higher than 1 because 3 and 4 have a subscription from the same student.
I have this query for now:
Select id_Course
From Subscription_Course
Group by id_Course
Having Count (id_Course)>1
I don't know what to do to add this condition to the count.
seems like you need to join to Subscription and count unique Student id's:
select id_Course
from Subscription_Course sc
join Subscription s
on s.idsubscription = sc.idsubscription
group by id_Course
having Count(distinct Studentid)>1
You can join the Subscription_Course table with the Subscription table in order to access the id_Student column. Then just count the distinct id_Student values for each id_Course value.
SELECT
Subscription_Course.id_Course,
COUNT(DISTINCT Subscription.id_Student) AS student_count
FROM Subscription_Course
INNER JOIN Subscription
ON Subscription_Course.id_Subscription = Subscription.id_Subscription
GROUP BY Subscription_Course.id_Course
HAVING COUNT(DISTINCT Subscription.id_Student) > 1
ORDER BY student_count DESC;
With result:
id_course | student_count
-----------+---------------
3 | 2
4 | 2
5 | 2

MS Access merge two tables

I need to create a new table base on two tables. I have a database in ms access and need to migrate.
tableT tableS
ID CustID DATE Exp1 Exp2 ID CustID DATE Tem1 Tem2
-------------------------------- ---------------------------------
1 1 1/1/00 5 5 1 1 1/1/00 3 4
2 2 1/1/00 1 3 2 2 1/1/00 5 0
3 1 3/1/00 3 2 3 1 5/1/00 0 3
4 3 4/1/00 4 1 4 3 6/1/00 0 0
Desired output table tableNew:
ID CustID DATE Exp1 Exp2 Tem1 Tem2
---------------------------------------------
1 1 1/1/00 5 5 3 4
2 2 1/1/00 1 3 5 0
3 1 3/1/00 3 2
4 3 4/1/00 4 1
5 1 5/1/00 0 3
6 3 6/1/00 0 0
If I use outer join, I will not get the output I need.
Any idea or help.
You want a full join. You can emulate this in MS Access using:
select t.CustID, t.DATE, t.Exp1, t.Exp2, s.tem1, s.tem2
from TableT as t left outer join
tableS as s
on t.CustId = s.CustId and t.date = s.date
union all
select s.CustID, s.DATE, null, null, s.tem1, s.tem2
from tableS as s left outer join
tableT as t
on t.CustId = s.CustId and t.date = s.date
where t.CustId is null;

Issue with SQL Group By and COALESCE on sqlite

I have a table as below in sqlite database. I want to create a line chart showing usage by product groups.
Table: ProductUsageData
UserID ProductName ProductGroup Qty RecordID
1 A1 A 12 1
2 A1 A 12 1
1 A2 A 15 1
3 A1 A 12 2
2 B1 B 12 2
5 B2 B 5 2
1 A1 A 12 3
1 A2 A 15 3
4 A1 A 12 3
3 C1 C 12 3
2 C2 C 15 3
Since I want separate line for each ProductGroup I am using below Query
SELECT
SUM(Qty) as UsedQty,
ProductGroup,
RecordID
FROM ProductUsageData
GROUP BY ProductGroup, RecordID
ORDER BY RecordID ASC;
While I get three records for A (for each RecordID) I get only 1 record each for B & C as they are not used during each RecordID.
Problem is when I am putting one line for each ProductGroup in the chart, the points for B & C are shown as per Qty in the first
My output is like this
A 39 1
A 12 2
B 17 2
A 39 3
C 27 3
So the graph looks like this
instead of
To fix this I changed the query using COALESCE to get 0 Qty if the ProductGroup is not used during each recording.
SELECT
COALESCE(SUM(Qty), 0) as UsedQty,
ProductGroup,
RecordID
FROM ProductUsageData
GROUP BY ProductGroup, RecordID
ORDER BY RecordID ASC;
I was expecting output as below
A 39 1
B 0 1
C 0 1
A 12 2
B 17 2
C 0 2
A 39 3
B 0 3
C 27 3
But I am getting same output as first
Please let me know how can I correct the query to get desired output
A typical solution is to first cross join two queries that select the distinct product groups and record ids from the table; this gives you all possible combinations of productGroup and recordID.
Then, you can bring in the original table with a left join, and aggregate:
select
g.productGroup,
coalesce(sum(p.qty), 0) qty,
r.recordID
from (select distinct productGroup from productUsageData) g
cross join (select distinct recordID from productUsageData) r
left join productUsageData p
on p.productGroup = g.productGroup
and p.recordID = r.recordID
group by r.recordID, g.productGroup
order by r.recordID, g.productGroup
In the real world, you might have separate referential tables for product groups and records ids, which would make the query simpler and more efficient (since it would avoid the need to select distinct in subqueries).
Demo on DB Fiddle:
productGroup | qty | recordID
:----------- | :-- | :-------
A | 39 | 1
B | 0 | 1
C | 0 | 1
A | 12 | 2
B | 17 | 2
C | 0 | 2
A | 39 | 3
B | 0 | 3
C | 27 | 3

filling running total over all month although its null

I have 2 tables. One only with all periods. Second with Account, Amount and period.
I want to build a View that lists Amount kumulated, period and account. Also if I don't have an fact for a period in my table should be appear the period in my view with the last amount.
select distinct
account, b.periode,
SUM(amount) OVER (PARTITION BY account ORDER BY b.periode RANGE UNBOUNDED PRECEDING)
from
fakten a
full join
perioden b on a.periode = b.periode
order by b.periode
it like this:
1 1 6
2 1 4
1 2 13
2 2 3
NULL 3 NULL
1 4 46
2 5 48
NULL 6 NULL
NULL 7 NULL
1 8 147
NULL 9 NULL
NULL 10 NULL
NULL 11 NULL
NULL 12 NULL
I need it like:
1 1 6
2 1 4
1 2 13
2 2 3
1 3 13
2 3 3
1 4 46
2 4 3
1 5 46
2 5 48
1 6 46
2 6 46
and so one...
Any ideas?
full join is not the right approach. Instead, generate the rows you want using a cross join. Then use left join and group by to do the calculation.
select a.account, p.periode,
SUM(f.amount) OVER (PARTITION BY a.account ORDER BY p.periode)
from (select distinct account from fakten) a cross join -- you probably have an account table, use it
perioden p
on a.periode = p.periode left join
fakten f
on f.account = a.account and f.periode = p.periode
group by a.account, p.periode
order by a.account, p.periode;

SQL query for 3 tables by tour

tourid
tourname
1
PARIS
2
LANDON
3
MADRID
tour_detail_ID
tourid
custid
1
1
3
2
2
3
3
3
3
4
1
4
5
2
4
6
3
4
7
1
5
8
2
5
custid
custname
custPhoneNo
3
PETER
22332422
4
MARY
22332422
5
PAUL
22332422
enter image description here
How can I get all customers booked all tours?
If I understand what your data is and what your question is, this will involve finding out who has not scheduled all of the tours and then finding all customers who aren't in the previous list.
I'm not sure I like it, but something like this gets just Peter and Mary, since they are the only two who have scheduled all 3 tours:
SELECT c1.custid, c1.custName
FROM #customers c1
LEFT OUTER JOIN (
SELECT c2.custid
FROM #tours t
CROSS JOIN #customers c2
LEFT OUTER JOIN #tour_detail td ON td.tourid = t.tourid
AND td.custid = c2.custid
WHERE td.custid IS NULL
) noCustTour ON c1.custid = noCustTour.custid
WHERE noCustTour.custid IS NULL