joining two tables by value of one column and calculating - sql

Thank you for interested in question.
I have in one table some thing like this
sifrez | sifKorisnikPK | Status
1 | 1 | 'P'
2 | 1 | 'P'
3 | 1 | 'U'
4 | 2 | 'P'
5 | 2 | 'P'
6 | 2 | 'U'
7 | 2 | 'U'
8 | 3 | 'U'
9 | 3 | 'U'
10 | 3 | 'U'
11 | 3 | 'U'
12 | 4 | 'P'
13 | 4 | 'P'
Then i created stored function which count values of P and U search ratio between them find user with that id and return username
CREATE PROCEDURE sp_getBestUsernames
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT SifKorisnikPK, COUNT (Status) AS BrojLosih
INTO #LosaRez
FROM Rezervacija
WHERE Status = 'P'
GROUP BY SifKorisnikPK
order by count(*) desc
After this part it give me
sifKorisnikPK | BrojLosih
1 | 2
2 | 2
4 | 2
This only count p on status.
And this:
SELECT SifKorisnikPK, COUNT (Status) AS BrojDobrih
INTO #DobraRez
FROM Rezervacija
WHERE Status = 'U'
GROUP BY SifKorisnikPK
order by count(*) desc
i get
sifKorisnikPK | BrojDobrih
1 | 1
2 | 2
3 | 4
Only count U. This part work like a charm...
And here i try to join this two temp tables and calculate ratio and return SifKorisnik with best ratio
SELECT Username FROM Korisnik
WHERE SifKorisnik = (SELECT TOP 1 a.SifKorisnikPK
FROM #DobraRez a
INNER JOIN #LosaRez b
ON a.SifKorisnikPK = b.SifKorisnikPK OR
a.SifKorisnikPK != b.SifKorisnikPK
WHERE a.BrojDobrih - b.BrojLosih > 0
ORDER BY a.BrojDobrih - b.BrojLosih )
END
And after joining operation i expect to get some thing like this, which i'm not getting
sifKorisnikPK | BrojDobrih | BrojLosih
1 | 1 | 2
2 | 2 | 2
3 | 4 | 0
4 | 0 | 2
so i can calculate the ratio BrojDobrih - BrojLosih and return the SifKorisnikPK which is the best ratio. In this case it would be SifKorisnik 3.
But my procedure get SifKorisnik 2 which is second best. I presume that the problem is in joining operation that it doesn't input 0. So how can i solve this?

Try this:
SELECT
A.sifKorisnikPK,
IsNull(BrojDobrih,0) BrojDobrih,
IsNull(BrojLosih,0) BrojLosih
FROM (select distinct sifKorisnikPK from Rezervacija) A
LEFT JOIN #LosaRez B
ON A.sifKorisnikPK = B.sifKorisnikPK
LEFT JOIN #DobraRez C
ON A.sifKorisnikPK = C.sifKorisnikPK
ORDER BY (IsNull(BrojDobrih,0) - IsNull(BrojLosih,0))

Related

MS SQL Query to get all entries comming multiple times in table where some column value doesnt have entries

I just tried to formulate title as best as possible. So my case is as follow.
i have a table
venue_id | style_id | is_main
1 | 1 | 1
1 | 2 | 0
1 | 3 | 0
2 | 5 | 0
2 | 8 | 0
2 | 9 | 0
3 | 3 | 1
4 | 4 | 1
4 | 6 | 0
5 | 7 | 0
5 | 8 | 0
5 | 9 | 0
So i need to get only those venue ID, witch coming more then once and where is no is_main true entry.
So result should be contain venue_id's: 2 and 5
I would grateful for any suggestion how such query may looks like.
Thanks in Advance.
UPD: in my case with is_amin BIT value answer would be:
select venue_id
from table
group by venue_id
having cast(max(cast(is_main as INT)) AS BIT) = 0 and
count(*) >= 2;
You seem to want:
select venue_id
from t
group by venue_id
having max(is_main) = 0 and
count(*) >= 2;
You can use this one:
SELECT DISTINCT v.venue_id FROM venue v
LEFT OUTER JOIN (SELECT DISTINCT venue_id FROM venue WHERE is_main=1) m
ON v.venue_id = m.venue_id
WHERE m.venue_id IS NULL
If you have many thousands of rows, it would be better to create a secondary table or a materialized view to be used in place of the nested SELECT.

How to get count from one table which is mutually dependent to another table

I have two table
Let's name as first table: QC_Meeting_Master
Second table: QC_Project_Master I want to calculate count of problems_ID Which is mutually depend on second table
ID | QC_ID | Problems_ID |
___|_______|_____________|
1 | 1 | 2 |
2 | 1 | 7 |
ID | QC_ID | Problem_ID |
___|_______|_____________|
1 | 1 | 7 |
2 | 1 | 7 |
3 | 1 | 7 |
4 | 1 | 7 |
5 | 1 | 2 |
6 | 1 | 2 |
7 | 1 | 2 |
select COUNT(Problem_ID) from [QC_Project_Master] where Problem_ID in
(select Problems_ID from QC_Meeting_Master QMM join QC_Project_Master QPM on QMM.Problems_ID = QPM.Problem_ID)
I have to calculate Count of QC_Project_Master (problem_ID) on basis of QC_Meeting_Master (Problems_ID)
it means for first table: QC_Meeting_Master(Problems_ID) = 2,
then count should be 3
And for Second table: QC_Project_Master (Problems_ID) = 7,
then count should be 4
use conditional aggregation
select sum(case when t2.Problem_ID=2 then 1 else 0 end),
sum(case when t2.Problem_ID=7 then 1 else 0 end) from
table1 t1 join table2 t2 on t1.QC_ID=t2.QC_ID and t1.Problems_ID=t2.Problems_ID
if you need all the group count then use below
select t2.QC_ID,t2.Problems_ID, count(*) from
table1 t1 join table2 t2
on t1.QC_ID=t2.QC_ID and t1.Problems_ID=t2.Problems_ID
group by t2.QC_ID,t2.Problems_ID
As far as I understood your problem this is simple aggregation and JOIN as below:
SELECT mm.QC_ID, mm.Problem_ID, pm.cnt
FROM QC_Meeting_Master mm
INNER JOIN
(
SELECT QC_ID, Problem_ID, COUNT(*) cnt
FROM QC_Project_Master
GROUP BY QC_ID, Problem_ID
) pm
ON pm.QC_ID = mm.QC_ID AND pm.Problem_ID = mm.Problem_ID;

Get right table data on LEFT JOIN

I have a problem with my sql join request.
I need to get lines of left table who are not referenced in right table for ME (User 1) or referenced in right table with status equal to 0 and user equal to 1.
I also need the field status of right table.
Here is my two tables :
Table left
ID | title
1 | Title 1
2 | Title 2
3 | Title 3
4 | Title 4
5 | Title 5
6 | Title 6
Table right
ID | status | user | left_id
1 | 0 | 1 | 1
2 | 0 | 50 | 1
3 | 1 | 1 | 2
4 | 0 | 50 | 2
5 | 0 | 1 | 3
6 | 1 | 50 | 3
7 | 0 | 50 | 4
8 | 1 | 50 | 5
My goal is to get this result :
left.ID | left.title | right.status | right.user
1 | Title 1 | 0 | 1
3 | Title 3 | 0 | 1
4 | Title 4 | NULL | NULL
5 | Title 5 | NULL | NULL
6 | Title 6 | NULL | NULL
Here is my request for the moment :
SELECT l.id, l.title, r.user, r.status
FROM left as l
LEFT JOIN right as r ON l.id = r.left_id
WHERE r.left_id IS NULL or (r.user = 1 AND r.status = 0)
With this request I get lines ID (left table) 1 / 3 / 6. But I also need the ID 4 / 5.
Those lines isn't displayed because another user (50) as a reference, but it's not me (1).
If someone can help me to add line 4 / 5 to my result I would be happy.
Thanks
Small improvement of the query should be sufficient:
SELECT l.id, l.title, r.user, r.status
FROM left as l
LEFT JOIN right as r ON l.id = r.left_id and r.user = 1
WHERE r.left_id IS NULL or r.status = 0
(Select t1.id, t1.title,t2.status,t2.user
from tableLeft t1
right outer join tableRight t2 on t2.left_id=t1.id
where t1.id not in
(select tt2.left_id from tableRight tt2)
)
union
(select t1.id,t1.title,t2.status,t2.user
from tableLeft t1
left join tableRight t2 on t1.id=t2.left_id
where t2.status=0 and t2.user=1
)

SQLite Optimize Query

I'm having trouble with SQLite query optimization, it runs fine, but for large tables it takes too much time and I need some help with optimizing it.
Source table:
-------+----------+----------------
IdMain | IdParent | ColumnToUpdate
-------+----------+----------------
1 | |
2 | 1 | 999 <-- IdParent = 1 \
3 | | \
4 | 5 | 123 > DISTINCT ITEMS COUNT = 1
5 | | / IdParent = 1
6 | 1 | 999 <-- IdParent = 1 / UPDATE Row with IdMain = IdParent
7 | 4 |
8 | 3 | 456
-------+----------+----------------
Query to optimize
UPDATE Table
SET ColumnToUpdate = (SELECT DISTINCT ColumnToUpdate
FROM Table T
WHERE T.ColumnToUpdate IS NOT NULL
AND T.IdParent = Table.IdMain)
WHERE Table.ColumnToUpdate IS NULL
AND (SELECT COUNT(*) FROM (SELECT DISTINCT ColumnToUpdate
FROM Table T2
WHERE T2.ColumnToUpdate IS NOT NULL
AND T2.IdParent = Table.IdMain)) = 1 ;
Expected table
-------+----------+----------------
IdMain | IdParent | ColumnToUpdate
-------+----------+----------------
1 | | 999 <-- UPDATE
2 | 1 | 999
3 | |
4 | 5 | 123
5 | |
6 | 1 | 999
7 | 4 |
8 | 3 | 456
-------+----------+----------------
Pseudo algorithm
FOR Row DO
BEGIN
IF ColumnToUpdate = NULL THEN
BEGIN
// count distinct values in ColumnToUpdate
X = COUNT(DISTINCT(ColumnToUpdate(WITH IdParent = IdMain))
// update row ONLY when number of distinct count equals = 1
IF X = 1 THEN
UPDATE(ColumnToUpdate)
END
END
I've tried to split it up within the source code (currently Delphi) but it works slow too. Is there any way to speed it up?
I wonder if this might speed things up:
UPDATE Table
SET ColumnToUpdate = coalesce((SELECT ColumnToUpdate
FROM Table T
WHERE T.ColumnToUpdate IS NOT NULL AND
T.IdParent = Table.IdMain
GROUP BY ColumnToUpdate
HAVING count(*) = 1),
Table.ColumnToUpdate
)
WHERE Table.ColumnToUpdate IS NULL;
This only executes the subquery once instead of twice.
Also, an index on Table(IdParent, ColumnToUpdate) might also improve performance.

SQL query handling three tables

I want to compile the data for reporting purpose, using php communicating with postgres,
I have three tables
product_status:
status_code | value
------------|------
1 | a
2 | b
product_child:
code| ID | status_code
----|----|------------
X | 1 | 1
X | 2 | 1
X | 3 | 2
Y | 1 | 2
Y | 2 | 2
Z | 1 | 1
product_master:
code|description(and some other columns not relevent)
X | la
Y | alb
Z | lab
In the end I want basically a table like this which i'll display
| total child | status a | status b
bla | 3 | 2 | 1
alb | 2 | 0 | 2
lab | 1 | 1 | 0
I have tried
SELECT s.value, count(s.value)
FROM product_child p, product_status s
WHERE
p.product_status = s.status_code
and p.product_code = get_product_code('Sofa (1-seater) J805')
group by
s.value
it gives we grouping for particular code but I want this flipped and appended in front of distinct product_codes
do you mean like this?
select pm.description,
count(pc.code) total,
count(case when ps.value = 'A' then ps.value else null end) statusA,
count(case when ps.value = 'B' then ps.value else null end) statusB
from product_master pm join product_child pc on pm.code = pc.code
join product_status ps on pm.status_code = ps.status_code
group by pm.description