sql join with not in column include in result - sql

I have two table like
id Name allocation
2 Ash 15
3 Alam 18
4 Rifat 20
and
Date Id Present
24 2 10
24 3 15
25 2 10
25 3 12
25 4 12
Now i want to get the following result
Date Id Alloc Present
24 2 15 10
24 3 18 15
24 4 20 NULL
25 2 15 10
25 3 18 12
25 4 20 12
I've tried JOIN query but it does not give desired result
How to get the above result?

SELECT
t1.id
, dd.date
, t1.allocation
, t2.present
FROM
table1 AS t1 --- all items
CROSS JOIN
( SELECT DISTINCT date
FROM table2
) AS dd --- all dates
LEFT JOIN
table2 AS t2 --- present allocations
ON t2.id = t1.id
AND t2.date = dd.date ;
Tested at SQL-Fiddle: test (thank you #JW.)

There is also an interesting other way:
SELECT
t2.date,
t1.id,
t1.allocation,
MAX(CASE WHEN t1.id = t2.id THEN t2.Present ELSE NULL END)
FROM
table1 t1, table2 t2
GROUP BY
t1.id, t2.date, t1.allocation
ORDER BY
t2.date, t1.id
Stolen from: SQL query inner join with 0 values
http://www.sqlfiddle.com/#!3/d2ded/44

Related

Countif statement in Postgresql

How can I use countif statement in PostgreSQL?
max(COUNTIF(t1.A1:C10,t2.a1),COUNTIF(t1.A1:C10,t2.b1),COUNTIF(t1.A1:C10,t2.c1))
I have table1 which is more then a million rows
a
b
c
M5
16
27
31
3
7
27
and table2 more then 100 rows including different dates after column c
a
b
c
10
15
16
30
40
50
60
70
80
16
18
37
5
12
16
8
31
28
11
12
13
7
9
31
2
7
21
20
16
27
8
12
17
2
8
14
3
14
15
The outcome should be something like this
a
b
c
M5
16
27
31
3
3
7
27
2
Tried the below query but the outcome is not correct
UPDATE table1 SET m5 = greatest(
case When a in(select unnest(array[a,b,c]) from (select * from table2 order by date DESC limit 10) foo) then 1 else 0 END,
case When b in(select unnest(array[a,b,c]) from (select * from table2 order by date DESC limit 10) foo) then 1 else 0 END,
case When c in(select unnest(array[a,b,c]) from (select * from table2 order by date DESC limit 10) foo) then 1 else 0 END)
Assuming your columns are fixed and predictable, I think you could put all possible table values into a single column and then do counts for each occurrence:
with exploded as (
select a from table2
union all
select b from table2
union all
select c from table2
)
select a, count (*) as count
from exploded e
group by a
So for example, the value 7 occurs twice (which would be reflected in this output).
From there, you can just do the updates from the CTE:
with exploded as (
select a from table2
union all
select b from table2
union all
select c from table2
),
counted as (
select a, count (*) as count
from exploded e
group by a
)
update table1 t
set m5 = greatest (ca.count, cb.count, cc.count)
from
counted ca,
counted cb,
counted cc
where
t.a = ca.a and
t.b = cb.a and
t.c = cc.a
The only issue I see is if one of the values does not come up (the inner join fails), but in your example that doesn't seem to happen.
If it is possible, I would think that could be resolved with one more CTE to fill in missing values from table1 in the set of possible occurrences.

Join 2 tables but have all value in condition column present in result

I have 2 tables like below
id
score1
1
4
2
5
3
6
id
score2
score3
2
7
9
3
8
10
4
7
9
5
8
10
And I want to join them together to achive this result
id
score1
score2
score3
total
1
4
0
0
4
2
5
7
9
21
3
6
8
10
24
4
0
7
9
16
5
0
8
10
18
How ever, i have tried all join type but the id column have null values in them, can you guys show me the solution for this? Thanks all
select
coalesce(t1.id,t2.id) id
, coalesce(t1.score1,0) score1
, coalesce(t2.score2,0) score2
, coalesce(t2.score3,0) score3
, coalesce(t1.score1,0) + coalesce(t2.score2,0) + coalesce(t2.score3,0) total
from table1 t1
full outer join table2 t2
on t1.id = t2.id
db<>fiddle here
SELECT COALESCE(C.ID,C2.ID)ID,COALESCE(C.SCORE1,0)SCORE1,
COALESCE(C2.SCORE2,0)SCORE2,COALESCE(C2.SCORE3,0)SCORE3,
COALESCE(C.SCORE1,0)+COALESCE(C2.SCORE2,0)+COALESCE(C2.SCORE3,0) TOTAL
FROM CTE AS C
FULL JOIN CTE2 C2 ON C.ID=C2.ID
ORDER BY ID
CTE - is yours first table(id,score1),CTE2 - second table(id,score2,score3)
You need to join in the ID.
Something like this (not tested) :
SELECT
t1.id,
ISNULL(t1.score1, 0)
ISNULL(t2.score2, 0)
ISNULL(t2.score3, 0)
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
LEFT JOIN instead of inner join or else you would only get lignes existing in t1

possibly left join with column value manipulation and condition check

SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t1.field_id = t2.field_id
WHERE t2.field_id IS NOT NULL
I'm trying to get the field_value from table 1 that does not exist in table 2
And add the row in table 2 and set is_selected = 0
I tried with join on t1.field_id = t2.field_id and t1.value_id != t2.field_value_lookup
Table 1
value_id field_id title
25 14 readonly1
26 14 readonly2
27 14 readonly3
1 13 optionA
2 13 optionB
Table 2
user_id field_id type_id field_value_lookup is_selected
260073 14 11 26 0
260073 14 11 27 1
Expected result in Table 2
user_id field_id type_id field_value_lookup is_selected
260073 14 11 26 0
260073 14 11 27 1
260073 14 11 25 0
Presuming Microsoft SQL Server
untested
select t2.user_id, t2.field_id, t2.type_id, t1.value_id field_value_lookup, 0 is_selected
from ( -- get the distinct existing information from table2 without field_value_lookup
select distinct user_id, field_id, type_id
from table2
) t2
inner join table1 t1 on t1.field_id = t2.field_id -- add all the values from table1
where not exists (select 1 -- exclude the rows that already exist
from table2
where user_id = t2.user_id
and field_id = t2.field_id
and type_id = t2.type_id
and field_value_lookup = t1.value_id
)

How to get the number of records from table 1 based on table 2 total count

Table1
Rowno name Date
------------------------------------
1 sathish Dec 21
2 kumar Dec 22
3 sathish Dec 21
4 sathish Dec 22
5 sathish Dec 21
5 sathish Dec 22
Table 2
Date NoofTran
-----------------------
Dec22 2
Dec21 1
I want to get the records from table1 based on the table2 nooftran values and randomly.
On Dec21st, there are 3 records and no of records to display is 2 and it should take it from randomly.
What SQL query should I use?
You can just join both the tables and order by the NoofTran
select Table1.*
from Table1 T1
inner join Table2 T2
on T1.[Date] = T2.[Date]
order by T2.NoofTran DESC
This will give you the result in NoofTran order
WITH CTE AS (
SELECT *, ROW_NUMBER()
OVER (
PARTITION BY T1.Date
order by NEWID()
) AS RN
FROM Table1 T1
)
SELECT CTE.RowNo,CTE.Date, CTE.Name
FROM CTE INNER JOIN Table2 T2
ON T2.date=cte.Date
WHERE RN <= T2.NoofTran

Get next minimum, greater than or equal to a given value for each group

given the following Table1:
RefID intVal SomeVal
----------------------
1 10 val01
1 20 val02
1 30 val03
1 40 val04
1 50 val05
2 10 val06
2 20 val07
2 30 val08
2 40 val09
2 50 val10
3 12 val11
3 14 val12
4 10 val13
5 100 val14
5 150 val15
5 1000 val16
and Table2 containing some RefIDs and intVals like
RefID intVal
-------------
1 11
1 28
2 9
2 50
2 51
4 11
5 1
5 150
5 151
need an SQL Statement to get the next greater intValue for each RefID and NULL if not found in Table1
following is the expected result
RefID intVal nextGt SomeVal
------------------------------
1 11 20 val01
1 28 30 val03
2 9 10 val06
2 50 50 val10
2 51 NULL NULL
4 11 NULL NULL
5 1 100 val14
5 150 150 val15
5 151 1000 val16
help would be appreciated !
Derived table a retrieves minimal values from table1 given refid and intVal from table2; outer query retrieves someValue only.
select a.refid, a.intVal, a.nextGt, table1.SomeVal
from
(
select table2.refid, table2.intval, min (table1.intVal) nextGt
from table2
left join table1
on table2.refid = table1.refid
and table2.intVal <= table1.intVal
group by table2.refid, table2.intval
) a
-- table1 is joined again to retrieve SomeVal
left join table1
on a.refid = table1.refid
and a.nextGt = table1.intVal
Here is Sql Fiddle with live test.
You can solve this using the ROW_NUMBER() function:
SELECT
RefID,
intVal,
NextGt,
SomeVal,
FROM
(
SELECT
t2.RefID,
t2.intVal,
t1.intVal AS NextGt,
t1.SomeVal,
ROW_NUMBER() OVER (PARTITION BY t2.RefID, t2.intVal ORDER BY t1.intVal) AS rn
FROM
dbo.Table2 AS t2
LEFT JOIN dbo.Table1 AS t1 ON t1.RefID = t2.RefID AND t1.intVal >= t2.intVal
) s
WHERE
rn = 1
;
The derived table matches each Table2 row with all Table1 rows that have the same RefID and an intVal that is greater than or equal to Table2.intVal. Each subset of matches is ranked and the first row is returned by the main query.
The nested query uses an outer join, so that those Table2 rows that have no Table1 matches are still returned (with nulls substituted for the Table1 columns).
Alternatively you can use OUTER APPLY:
SELECT
t2.RefID,
t2.intVal,
t1.intVal AS NextGt,
t1.SomeVal
FROM
dbo.Table2 AS t2
OUTER APPLY
(
SELECT TOP (1)
t1.intVal
FROM
dbo.Table1 AS t1
WHERE
t1.RefID = t2.RefID
AND t1.intVal >= t2.intVal
ORDER BY
t1.intVal ASC
) AS t1
;
This method is arguably more straightforward: for each Table2 row, get all matches from Table1 based on the same set of conditions, sort the matches in the ascending order of Table1.intVal and take the topmost intVal.
This can be done with a join, group by, and a case statement, and a trick:
select t1.refid, t2.intval,
min(case when t1.intval > t2.intval then t1.intval end) as min_greater_than_ref,
substring(min(case when t1.intval > t2.intval
then right('00000000'+cast(t1.intval as varchar(255)), 8)+t1.SomeVal)
end)), 9, 1000)
from table1 t1 left join
table2 t2
on t1.refid = t2.refid
group by t1.refid, t2.intval
SO, the trick is to prepend the integer value to SomeValue, zero-padding the integer value (in this case to 8 characters). You get something like: "00000020val01". The minimum on this column is based on the minimum of the integer. The final step is to extract the value.
For this example, I used SQL Server syntax for the concatenation. In other databases you might use CONCAT() or ||.