Join 2 tables with match of 2 columns from two tables - sql-server-2016

I have 2 tables :
TransferPointType
--------------------------------------------------
[Player(int)] [ID(int)] [Type(tinyint)] [Level(int)] [Before(money)] [Now(money)] [After(money)]
X
X
X
[Transfer]
--------------------------------------------------
[Player(int)] [ID(int)] [Type(tinyint)] [Amount(money)] [Created(datetime)] [Description(nvarchar256)]
The resulting table should look like this
[Player] [ID] [Level] [Before] [Now] [After] [Created] [Description]
--[Transfer] = TransferPointType--
and conditions
match between TransferPointType.player=[Transfer].player, TransferPointType.ID=[Transfer].ID
according to this match add others columns [Type] [Level] [Before] [Now] [After] from TransferPointType
and columns - [Created] [Description] from [Transfer]
-----------------------------------------------------------------------
where player=1111 and ID IN (1111,xxxx,xxx,xx,xx,xxx)
I think about the left join or union but I am not able to write a reasonable JOIN. If I tried UNION where i optimalized number of columns, I got to the point where the sql server show an error: Arithmetic overflow error -datetime. So, I tried to convert it with (example) select CONVERT(datetime, cast(20140806 as char(8)) ) without success either.
Maybe I'm thinking complicatedly and it could be written by simply select ...

Try this:
select a.type, a.level, a.before, a.now, a.after, b.created, b.description
from TransferPointType a
join Transfer b on a.player = b.player and a.ID = b.ID
where a.player = 1111
and a.ID IN (1111,xxxx,xxx,xx,xx,xxx);
If you expect TransferPointType has ID's that are not in Transfer table, then add "left" in front of join statement.

Related

How to get rid of the redundant information of a query and be left with only one row that contains all the information

Hello I have the following query in postgres. And I get the following result.
create temporary table "query_table" as
select
"airgoLocator_surgerytimes".iqnum as "surgery",
adminssion_time as "Admissió in",
pre_enter_time as "Preparació in",
quiro_enter_time as "Quiròfan in",
quiro_exit_time as "Quiròfan out",
recu_enter_time as "Recuperació in",
exit_time as "Sortida",
max(case when ("airgoLocator_phase".name='Inici anestèsia') then "airgoLocator_phasehistory".timestamp else NULL end) as Inici_anestesia,
max(case when ("airgoLocator_phase".name='Inici cirurgia') then "airgoLocator_phasehistory".timestamp else NULL end) as Inici_cirurgia,
max(case when ("airgoLocator_phase".name='Fi cirurgia') then "airgoLocator_phasehistory".timestamp else NULL end) as Fi_cirurgia,
max(case when ("airgoLocator_phase".name='Fi anestèsia') then "airgoLocator_phasehistory".timestamp else NULL end) as Fi_anestesia
from
"airgoLocator_surgerytimes"
inner join
"airgoLocator_surgery"
on
"airgoLocator_surgerytimes".iqnum = "airgoLocator_surgery".iqnum
inner join
"airgoLocator_phasehistory"
on
"airgoLocator_surgery".id = "airgoLocator_phasehistory".surgery_id
inner join
"airgoLocator_phase"
on
"airgoLocator_phasehistory".phase_id = "airgoLocator_phase".id
--where "airgoLocator_surgerytimes".iqnum = '0018571064'
group by "airgoLocator_surgerytimes".iqnum, "airgoLocator_surgerytimes".adminssion_time,
"airgoLocator_surgerytimes".pre_enter_time, "airgoLocator_surgerytimes".quiro_enter_time,
"airgoLocator_surgerytimes".quiro_exit_time, "airgoLocator_surgerytimes".recu_enter_time,
"airgoLocator_surgerytimes".exit_time, "airgoLocator_phase".name, "airgoLocator_phasehistory".timestamp,
"airgoLocator_surgerytimes".id, "airgoLocator_phasehistory".phase_id
order by "airgoLocator_surgerytimes".id desc, phase_id asc
;
select * from "query_table" where surgery = '0018571064';
My question is how can I get rid of the null fields and the repeated data so that I am left with a single row with all the information. For example like this:
Due to the way you are adding the rows into your temp table, with null values, we have to filter for the columns that do not have null values. You can get the result you want in two different ways. Using either group by, or using inner join on the same table multiple times. Here is an example of both:
Using group by:
select distinct
t1.surgury,
t1.Admission,
t1.preperation,
t1.Quirofan_in,
t1.Quirofan_out,
t1.recuperacion,
t1.sortida,
max(t1.inici_anestesia) [inici_anestesia],
max(t1.inici_cirurgia)[inici_cirurgia],
max(t1.fi_cirurgia)[fi_cirurgia]
from table2 t1
group by surgury, Admission, preperation, Quirofan_in, Quirofan_out, recuperacion, sortida
Using inner join method:
select distinct
t1.surgury,
t1.Admission,
t1.preperation,
t1.Quirofan_in,
t1.Quirofan_out,
t1.recuperacion,
t1.sortida,
t2.inici_anestesia,
t3.inici_cirurgia,
t4.fi_cirurgia
from table2 t1
inner join table2 t2 on t2.surgury=t1.surgury and t2.inici_anestesia is not null
inner join table2 t3 on t3.surgury=t1.surgury and t3.inici_cirurgia is not null
inner join table2 t4 on t2.surgury=t1.surgury and t4.fi_cirurgia is not null
I can tell you a solution, but you need to know your data and check if this solution does not match with your expected result.
You can remove those columns from group by clause and wrap them with MAX Function in SELECT clause.
But if the values in different rows (except null values) are different you miss them. In this case you may decide to use SUM function. It depends on your business goal.
Because your query is very long; I provide you a simple sample to understand.
Create Table Test (
ID int,
groupColumn1 int,
groupColumn2 int
)
INSERT Test (ID, groupColumn1, groupColumn2)
Values (1, 10, 20),
(1, 10, NULL),
(1, NULL, 20)
select ID, Max(groupColumn1) groupColumn1, MAX(groupColumn2) groupColumn2
From Test
Group by ID

Trying to combine this queries into one, because I want to write queries without using temp table. Keep getting syntax error

SELECT
CAST([patientDATA] AS XML).value('PatientcardCard[1]/Replacements[1]/patientId[1]', 'nvarchar(80)') [patientId]
,* into #tmp
FROM hospital [c1] with(NOLOCK)
where
patientserial in (
select ptserial From patients with(Nolock)
where patientsid=6889
and patientprogramid in (
26917,
21296,
27025
)
)
select patientId,patientbarcode,patientprogramID
into #tmp1
From #tmp
join patients with(nolock) on patientserial=ptserial
where patientid in
('0401478300007847',
'0401478300008566',
'0401478300008761',
'0401478300008727',
'0401478300007648',
'0401478300008020'
)
So first query is using cast to get value from a tag inside a column, the tag is patientID, and it is storing data into a temp table.
The second query is pulling the data from the temp table. I want to write a nested query without using temp table. But I keep syntax error, this is my query so far:
select patientId,patientbarcode,patientprogramID
From (
SELECT
CAST([patientDATA] AS XML).value('PatientcardCard[1]/Replacements[1]/patientId[1]', 'nvarchar(80)') [patientId]
,* into #tmp
FROM hospital [c1] with(NOLOCK)
where
patientserial in (
select ptserial From patients with(Nolock)
where patientsid=6889
and patientprogramid in (
26917,
21296,
27025
)
)
)
join patients with(nolock) on patientserial=ptserial
where patientid in
('0401478300007847',
'0401478300008566',
'0401478300008761',
'0401478300008727',
'0401478300007648',
'0401478300008020'
)
My error in SQL:
invalid column in first line, around patientId,patientbarcode
and in join part, invalid column as ptserial
Is it because the value is casted?
There are some problems with your approach.
SELECT * is not a good idea. It also appears to be unnecessary
for your final query.
You should reference which table each column
is coming from.
You may be overthinking this.
SELECT CAST([patientDATA] AS XML).value('PatientcardCard[1]/Replacements[1]/patientId[1]', 'nvarchar(80)') [patientId]
, patientbarcode
, patiendprogramID
FROM hospital h
INNER JOIN patients p ON p.ptserial = h.patientserial
WHERE patientsid = 6889
AND patientprogramid IN (26917, 21296, 27025)
AND patientid IN (
'0401478300007847'
,'0401478300008566'
,'0401478300008761'
,'0401478300008727'
,'0401478300007648'
,'0401478300008020'
)

Finding Not null on multiple columns using COALESCE

I have a query to find not null on 2 columns on a table which is a view , hence it is taking a lot of time for execution.
The query is : Query1
SELECT [Table1].M, [[Table1]].B, [Table1].P
FROM [Table1]
WHERE ((([[Table1]].B) Is Not Null) AND (([[Table1]].P) Is Not Null));
Does the below query does the same function as Query1 with faster execution time ?
SELECT [Table1].M, [[Table1]].B, [Table1].P
FROM [Table1]
WHERE COALESCE (([[Table1]].B),([[Table1]].P)) Is Not Null
Any help would be of great help and thanks in advance.
The view query
select dbo.TABLE1.[COL1]
, dbo.TABLE1.[COL2]
, RIGHT(dbo.TABLE1.M, 12) as M
, dbo.TABLE2.[MD]
, dbo.TABLE1.[COL3]
, dbo.TABLE1.[COL4]
, dbo.TABLE3.COL1
, dbo.TABLE3.[COL2]
, dbo.TABLE3.[COL3]
, dbo.TABLE4.[COL1]
, dbo.TABLE5.[COL1]
, dbo.TABLE6.[COL1]
, dbo.TABLE7.[COL1] as [BA]
, dbo.TABLE8.[COL1]
, dbo.TABLE3.[COL4]
, dbo.TABLE3.[COL5]
, dbo.TABLE3.[COL6]
from dbo.TABLE1
left outer join dbo.TABLE2
on dbo.TABLE1.M = dbo.TABLE2.M
left outer join dbo.TABLE3
on dbo.TABLE1.M = dbo.TABLE3.M
left outer join dbo.TABLE5
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE5.OBJ
left outer join dbo.TABLE6
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE6.OBJ
left outer join dbo.TABLE7
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE7.OBJ
left outer join dbo.TABLE4
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE4.OBJ
left outer join dbo.TABLE8
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE8.OBJ
where (
(
dbo.TABLE1.[COL1] not in (
'XX'
, 'YY'
)
)
and (dbo.TABLE1.COL5 = 'x')
)
No, both queries aren't equivalent.
The WHERE clause in the second one is equivalent to
WHERE [[Table1]].B Is Not Null OR [[Table1]].P Is Not Null
COALESCE will evaluate the first parameter and return it if not null. Otherwise, it will return the second one if not null, and so on, until reaching the last parameter, which will be returned whatever its value. So COALESCE(...) IS NOT NULL needs only one not null value to return true, not all.
I've tried this out on a table in my development DB. Here are the results:
with only PK index: 2 minutes for 4 million selected records out of 8 million table
with index on 3 selected columns (none of them PK) 1.8 seconds.
You might need to do some testing to get the right indexes for your setup but here is the sample of what i changed:
select [col1]
, [col2]
, [col3]
from [dbo].[tbl]
where col2 is not null
and col3 is not null
create nonclustered index [idx_test] on [dbo].[tbl] (
[col2] asc
, [col3] asc
) INCLUDE ([col1])

SQL Join With Fallback

Given
CREATE TABLE Addresses
Id INT NOT NULL
Zip NVARCHAR(5) NULL
ZipPlus4 NVARCHAR(9) NULL
CREATE TABLE ZipLookup
Zip NVARCHAR(5) NULL
Code NVARCHAR(10) NULL
CREATE TABLE ZipPlus4Lookup
ZipPlus4 NVARCHAR(9) NULL
Code NVARCHAR(10) NULL
And data like
Addresses
1 | 92123 | 921234444
ZipLookup
92123 | Type A
ZipPlus4Lookup
921234444 | Type B
Is it possible to construct a query such that:
A given row in Addresses is outer joined to ZipPlus4Lookup if there is a match
Addresses.ZipPlus4 = ZipPlus4Lookup.ZipPlus4
Otherwise, the given row in Addresses is outer joined to ZipLookup if there is a match
Addresses.Zip = ZipLookup.Zip
Otherwise neither table is outer joined
In plain English, the Addresses table has a Zip and a ZipPlus4 column and I need to look up a code using the most precise match. If there's a match on Zip+4, use the code from that match. Otherwise, use the code from a Zip match.
I wish I had an attempted query to share, but with this one I don't know where to start.
This basic query will work:
SELECT
A.*,
Code = IsNull(Z4.Code, Z.Code)
FROM
dbo.Addresses A
LEFT JOIN dbo.ZipPlus4Lookup Z4
ON A.ZipPlus4 = Z4.ZipPlus4
LEFT JOIN dbo.ZipLookup Z
ON A.Zip = Z.Zip
AND Z4.ZipPlus4 IS NULL;
Or you could try something like this:
SELECT
A.*,
Z.Code
FROM
dbo.Addresses A
OUTER APPLY (
SELECT TOP 1 Code
FROM (
SELECT 0, Code FROM dbo.ZipPlus4Lookup Z4
WHERE A.ZipPlus4 = Z4.ZipPlus4
UNION ALL
SELECT 1, Code FROM dbo.ZipLookup Z
WHERE A.Zip = Z.Zip
) X (Seq, Code)
ORDER BY X.Seq
) Z;
They may have different performance characteristics. It's worth testing. My guess is the second query is unnecessary but it's still conceptually possible to be better.
See these in action in a SQL Fiddle.

querying 2 tables with the same spec for the differences

I recently had to solve this problem and find I've needed this info many times in the past so I thought I would post it. Assuming the following table def, how would you write a query to find all differences between the two?
table def:
CREATE TABLE feed_tbl
(
code varchar(15),
name varchar(40),
status char(1),
update char(1)
CONSTRAINT feed_tbl_PK PRIMARY KEY (code)
CREATE TABLE data_tbl
(
code varchar(15),
name varchar(40),
status char(1),
update char(1)
CONSTRAINT data_tbl_PK PRIMARY KEY (code)
Here is my solution, as a view using three queries joined by unions. The diff_type specified is how the record needs updated: deleted from _data(2), updated in _data(1), or added to _data(0)
CREATE VIEW delta_vw AS (
SELECT feed_tbl.code, feed_tbl.name, feed_tbl.status, feed_tbl.update, 0 as diff_type
FROM feed_tbl LEFT OUTER JOIN
data_tbl ON feed_tbl.code = data_tbl.code
WHERE (data_tbl.code IS NULL)
UNION
SELECT feed_tbl.code, feed_tbl.name, feed_tbl.status, feed_tbl.update, 1 as diff_type
FROM data_tbl RIGHT OUTER JOIN
feed_tbl ON data_tbl.code = feed_tbl.code
where (feed_tbl.name <> data_tbl.name) OR
(data_tbl.status <> feed_tbl.status) OR
(data_tbl.update <> feed_tbl.update)
UNION
SELECT data_tbl.code, data_tbl.name, data_tbl.status, data_tbl.update, 2 as diff_type
FROM feed_tbl LEFT OUTER JOIN
data_tbl ON data_tbl.code = feed_tbl.code
WHERE (feed_tbl.code IS NULL)
)
UNION will remove duplicates, so just UNION the two together, then search for anything with more than one entry. Given "code" as a primary key, you can say:
edit 0: modified to include differences in the PK field itself
edit 1: if you use this in real life, be sure to list the actual column names. Dont use dot-star, since the UNION operation requires result sets to have exactly matching columns. This example would break if you added / removed a column from one of the tables.
select dt.*
from
data_tbl dt
,(
select code
from
(
select * from feed_tbl
union
select * from data_tbl
)
group by code
having count(*) > 1
) diffs --"diffs" will return all differences *except* those in the primary key itself
where diffs.code = dt.code
union --plus the ones that are only in feed, but not in data
select * from feed_tbl ft where not exists(select code from data_tbl dt where dt.code = ft.code)
union --plus the ones that are only in data, but not in feed
select * from data_tbl dt where not exists(select code from feed_tbl ft where ft.code = dt.code)
I would use a minor variation in the second union:
where (ISNULL(feed_tbl.name, 'NONAME') <> ISNULL(data_tbl.name, 'NONAME')) OR
(ISNULL(data_tbl.status, 'NOSTATUS') <> ISNULL(feed_tbl.status, 'NOSTATUS')) OR
(ISNULL(data_tbl.update, '12/31/2039') <> ISNULL(feed_tbl.update, '12/31/2039'))
For reasons I have never understood, NULL does not equal NULL (at least in SQL Server).
You could also use a FULL OUTER JOIN and a CASE ... END statement on the diff_type column along with the aforementioned where clause in querying 2 tables with the same spec for the differences
That would probably achieve the same results, but in one query.