Please advise SQL Update issue - sql

I have a SQL database with two tables
TableA (ID, State, Value)
1 England 20
2 France 50
3 USA 40
4 ........
5 ........
and
TableB (ID, username, age, stateID)
1 John 15 1
2 Adam 20 2
3 Jane 40 3
4 Scott 50 1
5 Edwin 60 2
6 Alex 20 3
7 Olsen 30 1
8 ...........
9 ...........
What I need is to update TableB by setting the age for all users
from England to be 20
and from France to be 50
and so on...

update tableB
set age = (select tableA.value from tableA where tableA.StateID=TableB.id)

I like this form below:
update b set
age = a.value
from tableB b
join tableA a on a.id = b.stateId
because you can write it this way (at last in SQL Server Management Studio):
update b set
age = a.value
--select b.age, a.value, b.*, a.*
from tableB b
join tableA a on a.id = b.stateId
then highlight the part from select ... to the end of query and execute it (F5) to check what you are going to change (value before and after).

Related

Using a Selected table for two sets of joins

I'm rationalising some old SQL tables that exist at a lot of remote sites, so I need to build a query that will make new good tables out of the bad old ones. So for this, we have table1 which has the columns DataGroup and Case1 as nvarchar, but these are enums in the application, so I've made new tables to store the enums, but I need to get the IDs. Unfortunately, we need to store all of the enums for this table in a single table, so the ExData table contains 4 columns: id, name, ExGroupId and DataGroupId.
As DataGroup in table1 is text, we need to look that up for the int id as well from a kvp table DataGroupTable
This is the query I have so far:
SELECT
<Other Columns>,
t1.ExDataId AS Case1
FROM
table1
LEFT JOIN (
SELECT
DataGroupTable.name AS dataGroup,
ExData.id AS ExDataId,
ExData.name AS ExDataName,
ExGroup.name AS ExGroupName
FROM
ExData
LEFT JOIN DataGroupTable ON DataGroupTable.id = ExData.dataGroupId
LEFT JOIN ExGroup ON ExGroup.id = ExData.ExGroupId
) t1 ON t1.dataGroup = table1.DataGroup
AND t1.ExGroupName = 'case1'
AND t1.ExDataName = table1.Case1
GO
... But while this works to retrieve Case1, how would I go about getting Case2?
I have 7 cases to handle, and whilst I could solve this with liberal copy-pasting, that is far from elegant.
Additionally, this is all going into an INSERT statment, so ideally this should return Case1, Case2 etc as ExDataId's
Please help.
Sample Data as requested, All id's will start from 0, but I have made all of the below unique for clarity.
table1:
DataGroup Case1 Case2 Case3 <Other Columns>
ABCD bob bob chris 1
ABCD pete gary chris 2
EFGH bob mike rod 3
DataGroupTable:
id name
11 ABCD
12 EFGH
ExGroup:
id name
21 case1
22 case2
23 case3
ExData:
id name ExGroupId dataGroupId
31 bob 21 11
32 pete 21 11
33 bob 21 12
34 bob 22 11
35 gary 22 11
36 mike 22 12
37 chris 23 11
38 rod 23 12
Ideal Result:
<Other Columns> Case1 Case2 Case3
1 31 34 37
2 32 35 38
3 33 36 38
How about a Common Table Expression ?
WITH ExDataCTE AS (
SELECT
DataGroupTable.name AS dataGroup,
ExData.id AS ExDataId,
ExData.name AS ExDataName,
ExGroup.name AS ExGroupName
FROM
ExData
LEFT JOIN DataGroupTable ON DataGroupTable.id = ExData.dataGroupId
LEFT JOIN ExGroup ON ExGroup.id = ExData.ExGroupId)
SELECT
<Other Columns>,
t1.ExDataId AS Case1,
t2.ExDataId AS Case2,
t3.ExDataId AS Case3
FROM
table1
LEFT JOIN ExDataCTE t1 ON (t1.dataGroup = table1.DataGroup
AND t1.ExGroupName = 'case1'
AND t1.ExDataName = table1.Case1)
LEFT JOIN ExDataCTE t2 ON (t2.dataGroup = table1.DataGroup
AND t2.ExGroupName = 'case2'
AND t2.ExDataName = table1.Case2)
LEFT JOIN ExDataCTE t3 ON (t3.dataGroup = table1.DataGroup
AND t3.ExGroupName = 'case3'
AND t3.ExDataName = table1.Case3)

Select 1 row query insert into multi row

I have existing data like this:
Table A
bill type amount
-----------------------------------
10 Food 100
11 Beverage 50
12 Food 200
Table Master GL:
Type D/C GL_CODE
-------------------------
Food D 12345
Food C 56789
Beverage D 88888
Beverage C 99999
I need to select all row in table A, insert this into below Table B
1 row in Table A will insert into 2 row in table B, also will select the GL code from table Master GL, to get the GL code.
D/C GL CODE Amount bill
-----------------------------------------
D 12345 100 10
C 56789 100 10
D 88888 50 11
C 99999 50 11
D 12345 200 12
C 56789 200 12
Can anyone advise me the query?
Thank you
you should join TableA with MasterGL on Type
In SQL Server
INSERT INTO TableB (DC, GL_CODE, Amount , bill)
SELECT M.DC,
M.GL_CODE,
A.Amount ,
A.bill
FROM TableA A
JOIN mastergl M
ON A.type = M.type

How to find out which column value changed in SQL

I have two tables with 100 of columns, and I want to find out how which column value changed in those two tables. I can find which row has changed but I want to which column was changed not the whole row.
Table 1
name ID Dept Email EmpID Salary Gender
Rob 1 IT I#i.com 100 5000 M
Mary 2 HR M#m.com 20 6000 F
Jack 3 IT J#j.com 30 7000 M
Harry 4 Fin h#h.com 50 5000 M
Jay 5 Eng Null 60 5000 M
Ken 6 HR K#K.com 70 Null M
Table 2
name ID Dept Email EmpID Salary Gender
Rob 1 IT I#i.com 100 5000 M
Mary 2 HR M#m.com 20 6000 F
Jack 3 IT J#j.com 150 7000 M
Harry 4 Fin h#h.com 50 Null M
Jay 5 Eng Jy#jy.com 60 5000 M
Ken 6 HR K#K.com 70 6000 M
As we can see Email for Jay existed, Emp ID for Jack was changed, Salary for Harry is null in Table 2 and Salary was added for Ken.
Expected Output (If this is possible, As I don't want to see all the row values, I just want to see which column value changed, as ID is a unique identifier, I would like to know which ID did column value change)
ID columnvaluechanged
3 EmpID
4 Salary
5 Email
6 Salary
Here is one way using unpivot technique
;WITH tab1
AS (SELECT id,
colName,
value
FROM Yourtable1
CROSS apply (VALUES (NAME,'name'),(Dept,'Dept'),(Email,'Email'),
(Cast(EmpID AS VARCHAR(50)),'EmpID'),
(Cast(Salary AS VARCHAR(50)),'Salary'),
(Gender,'Gender')) cs (value, colName)),
tab2
AS (SELECT id,
colName,
value
FROM Yourtable2
CROSS apply (VALUES (NAME,'name'),(Dept,'Dept'),(Email,'Email'),
(Cast(EmpID AS VARCHAR(50)),'EmpID'),
(Cast(Salary AS VARCHAR(50)),'Salary'),
(Gender,'Gender')) cs (value, colName))
SELECT t1.ID,
t1.colName,
t1.value AS tab1_value,
t2.value AS tab2_value
FROM tab1 t1
INNER JOIN tab2 t2
ON t1.ID = t2.ID
AND t1.colName = t2.colName
AND Isnull(t1.value, '') <> Isnull(t2.value, '')
Demo

Finding data from Table A and Table B relation

By see below tables how to (write query) get Table A data and status = InActive with no Data in Table B
Example : 4 Comm4 InActive
Table A
AID Name Status
-- --- --
1 comm1 Active
2 comm2 Active
3 Comm3 InActive
4 Comm4 InActive
5 Comm5 InActive
Table B
BID Name AID
--- ---- ---
11 James 1
12 Kris 2
13 Dan 3
14 Steve 3
15 Brian 5
It's quite simple
select * from tableA
where status = 'InActive'
and not exists (select * from tableB where tableA.AID = tableB.AID)
select tableA.*
from tableA
left join tableB
on tableA.AID = tableB.AID
and tableA.status = 'InActive'
where tableB.AID is null
The not exists from Szymon is correct and may be more efficient
Here you try.
select *
from #table_one
where Status = 'InActive'
and not exists
(
select 1 from #table_two where AID = #table_one.AID
);

Tricky SQL - Select non-adjacent numbers

Given this data on SQL Server 2005:
SectionID Name
1 Dan
2 Dan
4 Dan
5 Dan
2 Tom
7 Tom
9 Tom
10 Tom
How would I select records where the sectionID must be +-2 or more from another section for the same name.
The result would be:
1 Dan
4 Dan
2 Tom
7 Tom
9 Tom
Thanks for reading!
SELECT *
FROM mytable a
WHERE NOT EXISTS
(SELECT *
FROM mytable b
WHERE a.Name = b.Name
AND a.SectionID = b.SectionID + 1)
Here's LEFT JOIN variant of Anthony's answer (removes consecutive id's from the results)
SELECT a.*
FROM mytable a
LEFT JOIN mytable b ON a.Name = b.Name AND a.SectionID = b.SectionID + 1
WHERE b.SectionID IS NULL
EDIT: Since there is another interpretation of the question (simply getting results where id's are more than 1 number apart) here is another attempt at an answer:
WITH alternate AS (
SELECT sectionid,
name,
EXISTS(SELECT a.sectionid
FROM mytable b
WHERE a.name = b.name AND
(a.sectionid = b.sectionid-1 or a.sectionid = b.sectionid+1)) as has_neighbour,
row_number() OVER (PARTITION by a.name ORDER BY a.name, a.sectionid) as row_no
FROM mytable a
)
SELECT sectionid, name
FROM alternate
WHERE row_no % 2 = 1 OR NOT(has_neighbour)
ORDER BY name, sectionid;
gives:
sectionid | name
-----------+------
1 | Dan
4 | Dan
2 | Tom
7 | Tom
9 | Tom
Logic: if a record has neighbors with same name and id+/-1 then every odd row is taken, if it has no such neighbors then it gets the row regardless if it is even or odd.
As stated in the comment the condition is ambiguous - on start of each new sequence you might start with odd or even rows and the criteria will still be satisfied with different results (even with different number of results).