Filtering the distinct rows from Table - sql-server

I have a table with two columns schema as:
ID1,ID2
Values are as:
x y
y x
a b
b a
I just want resultset as a whole like:
x y
a b
I want to remove duplicate
Need the sql query for the same.

One of the ways to achieve this is to use LEFT JOIN like this.
SQL Fiddle
Query
SELECT T1.ID1,T1.ID2
FROM YourTable T1
LEFT JOIN YourTable T2
ON T1.ID1 = T2.ID2
AND T1.ID2 = T2.ID1
AND T2.ID1 < T2.ID2
WHERE T2.ID1 IS NULL
Output
| ID1 | ID2 |
|-----|-----|
| x | y |
| a | b |

I suggest you to use EXISTS like this:
SELECT *
FROM yourTable t
WHERE NOT EXISTS(SELECT 1 FROM yourTable ti
WHERE t.ID1 = ti.ID2 AND t.ID2 = ti.ID1
AND ti.ID1 > ti.ID2)

Related

Join 2 tables with string_id instead of jointable

I want to join 2 tables but there is no join table between them... I usually use STRING_SPLIT but in this case, I can't figure it out. Maybe I'm just tired... Could you help me please ?
CREATE TABLE ##Provider
(
id INT,
p_name VARCHAR(50),
list_id_dep VARCHAR(250)
)
CREATE TABLE ##Department
(
id INT,
d_name VARCHAR(50)
)
INSERT INTO ##Provider (id, p_name, list_id_dep) VALUES
(1, 'toto', '/10/11/12/'),
(2, 'tata', '/09/');
INSERT INTO ##Department (id, d_name) VALUES
(9, 'dep9')
,(10, 'dep10')
,(11, 'dep11')
,(12, 'dep12');
What I want is :
id | p_name | d_name
--------------------------
1 | toto | dep10
1 | toto | dep11
1 | toto | dep12
2 | tata | dep09
I've tried :
select *
from ##Provider p
inner join ##Department d on STRING_SPLIT(p.list_id_dep, '/') = ???
select *
from ##Provider p
inner join STRING_SPLIT(p.list_id_dep, '/') dep ON dep.value = ???
select *
from ##Provider p, ##Department d
where (select value from STRING_SPLIT(p.list_id_dep, '/')) = d.id
select *
from ##Provider p, ##Department d
where d.id in (select value from STRING_SPLIT(p.list_id_dep, '/'))
Maybe STRING_SPLIT is not the right way to do it...
Thanks !
You need a lateral join to unnest the string - in SQL Server, this is implented with cross apply. Then, you can bring the department table with a regular join:
select p.id, p.p_name, d.d_name
from ##provider p
cross apply string_split(p.list_id_dep, '/') x
inner join ##department d on d.id = x.value
Demo on DB Fiddle:
id | p_name | d_name
-: | :----- | :-----
1 | toto | dep10
1 | toto | dep11
1 | toto | dep12
2 | tata | dep9

How to join columns from the same table?

How to add extra column with time difference for the same SALESID and GO = SO and GO = ZW?
select SALESID, DATETIME AS Time, GO
FROM [Mer_PRD].[dbo].[TRACKINGTABLE]
WHERE GO IN('ZW', 'SO')
Result example:
****SALESID** | TIME SO | TIME ZW | DIFF**
ZS/0033428/2020 | 2020-07-16 08:37:00 | 2020-07-16 08:40:00 | 00:03:00
You could use a self join.
SELECT goSO.SALESID
, goSo.[Time] 'TIME SO'
, goZw.[Time] 'TIME ZW'
, cast(goZw.[Time] - goSo.[Time] as Time) Difference
FROM GOTRACKING goSo
INNER JOIN GOTRACKING goZw on goSo.SALESID = goZw.SALESID
WHERE goSo.[GO] = 'SO'
AND goZw.[GO] = 'ZW'
SQLFiddle
try this,
SELECT SALESID, Time FROM [Mer_PRD].[dbo].[TRACKINGTABLE]
;WITH cte AS (SELECT SALESID, Time, ROW_NUMBER()OVER(PARTITION BY SALESID ORDER BY Time) AS RN
FROM [Mer_PRD].[dbo].[TRACKINGTABLE])
SELECT a.SALESID, a.Time, b.Time AS Time2
FROM cte a
LEFT JOIN cte b
ON a.SALESID = b.SALESID
AND a.RN = b.RN -1
WHERE a.RN = 1

How to Join to "Other" row

I have two tables. One holds Objects and the other holds Settings about each object. Not all of the rows in the Objects table have a corresponding row in the Settings table. There is a special row in the Settings table that is supposed to be used for the "Other" objects.
How can I create a join between Objects and Settings such that I get the given setting if there is one or the "Other" setting if there isn't?
For example consider the following script:
CREATE TABLE #Objects (Code nvarchar(20) not null);
CREATE TABLE #Settings (Code nvarchar(20) not null, Value int not null);
INSERT INTO #Objects
VALUES
('A'),
('B'),
('D')
INSERT INTO #Settings
VALUES
('A', 1),
('B', 2),
('C', 3),
('Other', 4)
SELECT
#Objects.Code,
#Settings.Value
FROM
#Objects
JOIN #Settings
ON #Objects.Code = #Settings.Code
OR #Settings.Code = 'Other'
DROP TABLE #Settings, #Objects
I'm wanting to get this:
Code | Value
---- | -----
A | 1
B | 2
D | 4
What I'm actually getting is:
Code | Value
----- | -----
A | 1
A | 4
B | 2
B | 4
D | 4
You can do this with an APPLY:
SELECT o.Code, s.Value
FROM #Objects o
CROSS APPLY (
SELECT TOP 1 *
FROM #Settings s
WHERE s.Code = o.Code or s.Code = 'Other'
ORDER BY case when s.Code = o.Code then 0 else 1 end
) s
For fun: a hybrid from answers by Gurv, jyao and SqlZim, which are all variations on the same basic theme:
SELECT o.Code, s2.Value
FROM #Objects o
LEFT JOIN #Settings s1 on s1.Code = o.Code
INNER JOIN #Settings s2 on s2.Code = coalesce(s1.Code, 'Other')
So far, this approach (LEFT JOIN + the INNER JOIN ON COALESCE() ) is my favorite option.
Note that this only works if there can be only one Settings record per Object record. If that ever changes, the APPLY answer still works, but other answers here might not work.
Another way is to use CTE to add an additional column [Alternative_code] for [#Object] table that has value "Other" for [Code] not existing in [#Settings]
and then using this CTE to join with #Settings table as shown below
; with c as (
select alternative_Code = isnull(s.code, 'Other'), o.Code
from #Objects o
left join #Settings s
on o.Code = s.Code)
select c.Code, s.value
from c
inner join #Settings s
on c.alternative_Code = s.Code
Using a left join to get null where o.Code has no match in #Settings
, and using coalesce() to return the designated replacement value
from #Settings when s.Value is null.
You could use isnull() instead of coalesce, the result would be the same in this instance.
I am not sure if this acceptable, but it returns the correct results:
select
o.Code
, coalesce(s.Value,x.Value) as Value
from #Objects o
left join #Settings s
on o.Code = s.Code
cross join (
select top 1 value
from #Settings
where Code = 'Other'
) x
rextester demo: http://rextester.com/EBUG86037
returns:
+------+-------+
| Code | Value |
+------+-------+
| A | 1 |
| B | 2 |
| D | 4 |
+------+-------+
In the form #RBarryYoung prefers:
select
o.Code
, coalesce(s.Value,x.Value) as Value
from #Objects o
left join #Settings s
on o.Code = s.Code
inner join #Settings x
on x.Code = 'Other'
This is more concise (saves you many keystrokes) and generates the same execution plan as my initial answer. Whether it is more or less clear about what it is doing is up to you, I like both.
If there is going to be one "Other" value then you can just do the join twice - a left join and another one which is effectively a cross join:
select o.Code,
coalesce(s.Value, s2.value) as value
from #Objects o
left join #Settings s on o.Code = s.Code
join #Settings s2 on s2.Code = 'Other'

Update a table using temp table with select statement for multiple rows

I have temp table in my SP and a table in my DB and I need to update the table in the DB, and as of now I am able to update the table using select statement.
But I am having multiple records in my temp table and I am able to update only my last row of the table in DB.
Below is the query I am having,
UPDATE
Table_A
SET
Table_A.col2 = Table_B.col2,
Table_A.col3 = Table_B.col3
FROM
Some_Table AS Table_A
INNER JOIN temp_Table AS Table_B ON Table_A.col1 = Table_B.col1
And DB table structures
col1 | col2 | col3
1 | India | Delhi
2 | US | NewYork
3 | UK | London
And temp table structure as below
col1 | col2 | col3
1 | US | NewYork
2 | UK | London
3 | India | Delhi
So, I need to update my table for multiple rows.
As far as I am understanding your post I think this should be the solution for that which will update properly. Hope this helps
WITH CTE1
AS ( SELECT Col1 ,
Col2 ,
ROW_NUMBER() OVER ( PARTITION BY COl1 ORDER BY Col2 ) AS rn
FROM table_1 t1
),
CTE2
AS ( SELECT Col1 ,
Col2 ,
ROW_NUMBER() OVER ( PARTITION BY COl1 ORDER BY Col2 ) AS rn
FROM table_2 t2
)
UPDATE br
SET ....
FROM Cte1 c1
INNER JOIN cte2 c2 br ON c1.Col1 = c2.Col1
AND c1.rn = c2.rn;

SQL Creating a view with an additional sum column

Hi I'm trying to create a view from two different tables that has an additional column that is a sum of Table1.Price1 - Table2.Price2. The view without the additional column is:
Create View testview AS (
SELECT t1.ID,t1.Price1,t2.Price2 FROM
Table1 t1
LEFT JOIN
Table2 t2
ON
t1.ID = t2.ID
);
Any help would be much appreciated, thank you.
Below is a representation of what the view would look like:
ID | Table1.Price1 | Table2.Price2 | Total |
---------------------------------------
1 | 15.00 | 5.00 | 10.00 |
2 | 10.00 | 2.50 | 7.50 |
Try this:
Create View testview AS
(SELECT t1.ID,t1.Price1,t2.Price2, (t1.Price1 - t2.Price2) as difference
FROM Table1 t1
LEFT JOIN Table2 t2
ON t1.ID = t2.ID );
Just add your SUM column, like this:
Create View testview AS (
SELECT t1.ID,t1.Price1,t2.Price2, t1.Price1-t2.Price2 AS [SUM] FROM
Table1 t1
LEFT JOIN
Table2 t2
ON
t1.ID = t2.ID
);
You can just add two columns with the +,-,*,/ operators like in:
Create View testview AS (
SELECT t1.ID,t1.Price1,t2.Price2, t1.Price1+t2.Price2 as total FROM
Table1 t1
LEFT JOIN
Table2 t2 ON t1.ID = t2.ID
);
This will result in your desired table structure

Resources