How can i update a table from select statement results. Here is my select statement:
SELECT count(distinct r.[ID])as Total
FROM Table1 r left join
Tabel2 a
on r.ID = a.ID
where a.Status is null
and here is like what i want to do and i know it is wrong:
update MyTable
set mycol = total
from
(
SELECT count(distinct r.[ID])as Total
FROM Table1 r left join
Tabel2 a
on r.ID = a.ID
where a.Status is null)
Use the subquery in the set:
update MyTable
set mycol = (
SELECT count(distinct r.[ID])
FROM Table1 r left join
Tabel2 a
on r.ID = a.ID
where a.Status is null
)
All you have to do is make a couple tiny changes. Below is the code you will need to use:
update MyTable
set mycol = (SELECT count(distinct r.[ID])as Total
FROM Table1 r left join
Tabel2 a
on r.ID = a.ID
where a.Status is null)
In the case that, as I assume, you have multiple rows in both tables and you want to update the first table row-by-row with related results from your subquery, you'll want to add a join (assuming that both datasets will have what i am calling 'identifyingfield' below) :
Update MyTable
set mycol = b.total
from
MyTable a
inner join
(
SELECT identifyingfield, count(distinct r.[ID])
FROM Table1 r left join
Tabel2 a
on r.ID = a.ID
where a.Status is null
group by identifyingfield
) b
ON a.identifyingfield = b.identifyingfield
you may try something like this:
with "sums"
as
(
select
F."id"
, "sum" = sum( F."value" ) over ( partition by F."id" )
from
"foo" F
)
update
B
set
B."totals" = S."sum"
from
"bar" B
inner join "sums" S
on S."id" = B."id";
see sql-fiddle here
Related
How do I update table1 with results of this query -
select b.description from
table1 c
join
(
SELECT distinct a.hcpc, a.description
FROM table2 a
) b
on b.hcpc = c.hcpc
where c.description = '0'
I want to do something like this -
update table1
set table1.description = (select b.description from table1 c
join
(
SELECT distinct a.hcpc, a.description
FROM table2 a
) b
on b.hcpc = c.hcpc
where c.description = '0'
)
This question has been answered many times in SO... anyway, the query should be built this way
One option
update table1 c
set description = b.description
from
(
SELECT distinct a.hcpc, a.description
FROM table2 a
) b
where b.hcpc = c.hcpc
and c.description = '0'
Other option
with t as (
SELECT distinct a.hcpc, a.description
FROM table2 a
)
update table1 c
set description = t.description
from t
where t.hcpc = c.hcpc
and c.description = '0'
Surely there are other additional ways...
I want to combine all the related data using LEFT JOIN clause but if one of tables has no matched record from other table it will not show up. Can you check my queries it seems that there is missing or totally messed up. Here's my query.
SELECT*
FROM
MASTER_TBL
LEFT JOIN
(
SELECT*
FROM
TBLA A
LEFT JOIN
TBLB B
ON
A.ID=B.ID AND A.DESC=B.DESC
LEFT JOIN
TBLC C
ON
B.ID=C.ID AND B.DESC=C.DESC
LEFT JOIN
TBLD D
ON
C.ID=D.ID AND C.DESC=D.DESC
) E
ON
MASTER_TBL.ID=E.ID
The problem is that you are cascading the conditions across joins. For example, here are the join conditions for table d:
C.ID = D.ID AND C.DESC = D.DESC
For this to match, you need to have a matching row in C already.
As your query stands, it looks like you can use the id from the master table to search all the following tables. As for the desc columns, it looks like your best pick is to use that of table a.
So, consider:
select *
from master_tbl m
left join tbla a on a.id = m.id
left join tblb b on b.id = m.id and b.desc = a.desc
left join tblc c on c.id = m.id and c.desc = a.desc
left join tbld d on d.id = m.id and d.desc = a.desc
If all descs are not available in tablea, we could switch to full joins. The logic is more complicated to follow, but that would look like:
select *
from master_tbl m
full join tbla a on a.id = m.id
full join tblb b on b.id = m.id and b.desc = a.desc
full join tblc c on c.id = m.id and c.desc = coalesce(a.desc, b.desc)
full join tbld d on d.id = m.id and d.desc = coalesce(a.desc, b.desc, c.desc)
This approach uses UNION ALL to combine the letter named tables (tbla, tblb, tblc, tbld) into a CTE, common table expression. The combined table is then summarized by id, [desc] and crosstabulated (or pivoted) across the login columns. The pivoted result is then LEFT JOIN'ed to the master_tbl. Something like this.
with
tbl_cte(tbl, id, [login], [desc]) as (
select 'A', * from tbla
union all
select 'B', * from tblb
union all
select 'C', * from tblc
union all
select 'D', * from tblc),
pvt_cte(id, tbla_login, tblb_login, tblc_login, tbld_login, [desc]) as (
select id,
max(case when tbl='A' then [login] else null end) as tbla_login,
max(case when tbl='B' then [login] else null end) as tblb_login,
max(case when tbl='C' then [login] else null end) as tblc_login,
max(case when tbl='D' then [login] else null end) as tbld_login,
[desc]
from tbl_cte
group by id, [desc])
select mt.id, [name], country, [status], pc.tbla_login,
pc.tblb_login, pc.tblc_login, pc.tbld_login, pc.[desc]
from master_tbl mt
left join pvt_cte pc on mt.id=pc.id;
I have 2 tables - table1 and table2.
In table2, there are multiple records matching criteria for table1 based on:
c_type, h_level, loop, e_id
I want records from RIGHT table ONLY if there is EXACT 1 match. If not, element_nm should be NULL, so I have the exact same records in the output as left table.
SELECT a.*,
b.element_nm
FROM table1 a
LEFT JOIN table2 b ON
a.c_type = b.c_type
AND a.h_level = b.h_level
AND a.loop = b.loop
AND a.e_id = b.e_id
ORDER BY a.file_name,
a.line_num asc;
As this is about one value only, you can use a Sub query in the select clause. Otherwise you'd use a subquery in a LEFT OUTER JOIN or use OUTER APPLY.
SELECT
t1.*,
(
SELECT MIN(t2.element_nm)
FROM table2 t2
WHERE t2.c_type = t1.c_type
AND t2.h_level = t1.h_level
AND t2.loop = t1.loop
AND t2.e_id = t1.e_id
HAVING COUNT(*) = 1
) AS element_nm
FROM table1 t1
ORDER BY t1.file_name, t1.line_num;
Thorsten's answer works when you want only one column from the second table. But if you want multiple columns, it is a bit cumbersome.
Alternatively:
SELECT a.*, b.*
FROM table1 a LEFT JOIN
(SELECT b.*,
COUNT(*) OVER (PARTITION BY b.c_type, b.h_level, b.loop, b.e_id) as cnt
FROM b
) b
ON a.c_type = b.c_type AND
a.h_level = b.h_level AND
a.loop = b.loop AND
a.e_id = b.e_id AND
b.cnt = 1
ORDER BY a.file_name, a.line_num asc;
you should use Row_Number , like this :
WITH cte AS (
SELECT ROW_NUMBER() OVER(PARTITION BY a.c_type ,a.h_level,a.loop ,a.e_id ) rnum
,a.c_type ,a.h_level,a.loop ,a.e_id FROM table1 a
LEFT JOIN table2 b ON a.c_type = b.c_type AND a.h_level = b.h_level AND a.loop = b.loop AND a.e_id = b.e_id
)
,cte2 AS (SELECT * FROM cte WHERE rnum = 2)
SELECT a.*,
CASE WHEN cte2.element_nm IS NULL then b.element_nm ELSE NULL END element_nm
FROM table1 a
LEFT JOIN table2 b ON a.c_type = b.c_type AND a.h_level = b.h_level AND a.loop = b.loop AND a.e_id = b.e_id
LEFT JOIN cte2 ON a.c_type = cte2.c_type AND a.h_level = cte2.h_level AND a.loop = cte2.loop AND a.e_id = cte2.e_id
Is there any alternate way to fetch the following data without using union?
select A.name,A.age,B.Address,C.phoneNo from table1 A,Table2 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId
union
select A.name,A.age,B.Address,C.phoneNo from table4 A,Table5 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId
I am using this in Hibernate and unfortunately hibernate doesnt support Union. I was just wondering if there is any other way to achieve it else ill have to write it in a procedure and save the data in temp table and fire a sql to read data from that temp table
There is an alternative for union, but it is not pretty:
select distinct coalesce(x1.name, x2.name) as name,
coalesce(x1.age, x2.age) as age,
coalesce(x1.Address, x2.Address) as age,
coalesce(x1.phoneNo, x2.phoneNo) as age,
from (select A.name, A.age, B.Address, C.phoneNo
from table1 A join
Table2 B
on a.pkId = b.FkId join
Table3 C
on b.pkId = c.FkId
) x1 full outer join
(select A.name, A.age, B.Address, C.phoneNo
from table4 A join
Table5 B
on a.pkId = b.FkId join
Table3 C
on b.pkId = c.FkId
) x2
on 1 = 0; -- always false
I can't imagine why you would want to express a union like this. I would highly recommend, though, that you start using proper, explicit join syntax.
is this working ?
SELECT
CASE DISTINCT_FLG WHEN 1 THEN nameA ELSE nameB END name,
CASE DISTINCT_FLG WHEN 1 THEN ageA ELSE ageB END age,
CASE DISTINCT_FLG WHEN 1 THEN AddressA ELSE AddressB END Address,
CASE DISTINCT_FLG WHEN 1 THEN phoneNoA ELSE phoneNoB END phoneNo
FROM (
SELECT
T1.name AS nameA, T1.age AS ageA, T2.Address AS AddressA, T3.phoneNo AS phoneNoA,
T4.name AS nameB, T4.age AS ageB, T5.Address AS AddressB, T3.phoneNo AS phoneNoB,
ROW_NUMBER() OVER(PARTITION BY T1.name, T1.age, T2.Address, T4.name, T4.age, T5.Address, T3.phoneNo ORDER BY NULL) AS DISTINCT_FLG
FROM
table1 T1,
table2 T2,
table4 T4,
table5 T5,
table3 T3
WHERE
T1.pkId = T2.FkId AND
T4.pkId = T5.FkId AND
(
T2.pkId = T3.FkId OR
T5.pkId = T3.FkId
)
) WHERE DISTINCT_FLG IN (1, 2)
Those two UNION parts have Table3 C in common, so we can join the rest to it. To emulate UNION records from the source table can be replicated through unconditional cross join of an auxiliary table with the required number or rows:
Select Distinct
CASE R.r WHEN 1 THEN A1.name ELSE A2.name END As name ,
CASE R.r WHEN 1 THEN A1.age ELSE A2.age END As age ,
CASE R.r WHEN 1 THEN B1.Address ELSE B2.Address END As Address,
C.phoneNo
From Table3 C, --< Start at common Table3
(Select Rownum r From USER_TABLES Where Rownum < 3) R --< Two rows to replicate Table3 C
-- Any table with more than one row will do
-- USER_TABLES should have enough rows in this particular case
Left Join Table2 B1 On R.r = 1 AND B1.pkId = C.FkId --< Left Join branch one
Left Join table1 A1 On R.r = 1 AND A1.pkId = B1.FkId
Left Join Table5 B2 On R.r = 2 AND B2.pkId = C.FkId --< Left Join branch two
Left Join table4 A2 On R.r = 2 AND A2.pkId = B2.FkId
Where (R.r = 1 AND A1.pkId Is NOT NULL) --/ Make sure we have values
OR (R.r = 2 AND A2.pkId Is NOT NULL) --\ for the branch
But really, consider a view.
Not sure how to rewrite the below query. I’m trying to join table_a to the most recent table_b record. Currently testing for only one ID, but a different criteria on table_a may be added:
Select t.*
from table_a t
left join table_b d on d.id = T.id and d.MOD_DATE IN (SELECT MAX(mod_date) FROM table_b d2 WHERE d2.id = t.id)
where T.id = 123456
Any suggestions?
I think you are looking for something like:
SELECT t.*
FROM table_a t
LEFT JOIN (
SELECT d.*
FROM table_b d
INNER JOIN (
SELECT id
, MAX(mod_date) mod_date_max
FROM table_b d2
GROUP BY id
) db
ON db.id = d.id
AND db.mod_date_max = d.mod_date
) d
ON d.id = T.id
WHERE T.id = 123456
Note that your where clause turns the left join into an inner join.
Also, if you get an error, please post the error message as well, not just its number.
I also found the same could be achieved with the following query:
SELECT * FROM table_a t
WHERE id IN (
SELECT id
FROM (
SELECT id,MAX(MOD_DATE)
FROM table_b
WHERE id = 123456
GROUP BY id
)
)