sql puzzle sql server 2000 - sql

I have a small puzzle for myself.
PK is combination of lineNr and typeNr
i want to make a selection where all is_adres is N and the same for all linenrs, the same goes for is_postaddres. And I want the result in one view.
this is wat i want as end result
typenr,is_Adres ,is_postaddres
10, null , 'N'
11, 'N', null
13, 'N', 'N'
create table script + testdata
CREATE TABLE lineAdres
(
lineNr int,
typeNr int,
is_Adres char(1),
is_postaddres char(1)
);
INSERT INTO lineAdres VALUES
(1, 10,'J','N'),
(1, 11,'N','J'),
(1, 12,'N','J'),
(1, 13,'N','N'),
(2, 10,'J','N'),
(2, 11,'N','J'),
(2, 12,'J','N'),
(2, 13,'N','N');
I want to join this 2 views in one.. but how, and i got a feeling it could be more efficient!
select typenr, is_adres
from lineAdres
where is_adres = 'N'
group by typenr, is_adres
having count(*) = 2
select typenr, is_postaddres
from lineAdres
where is_postaddres = 'N'
group by typenr, is_postaddres
having count(*) = 2

To join the two result use a CTE and a full join to combine the data.
WITH IsAddress AS(
select typenr, is_adres
from lineAdres
where is_adres = 'N'
group by typenr, is_adres
having count(*) = 2),
IsPostAddress AS (select typenr, is_postaddres
from lineAdres
where is_postaddres = 'N'
group by typenr, is_postaddres
having count(*) = 2)
SELECT
COALESCE(IsAddress.typenr,IsPostAddress.typenr) typenr,
IsAddress.IsAddress,
IsPostAdress.is_postaddres
FROM
IsAddress
FULL OUTER JOIN
IsPostAdress
ON
IsAddress.typenr = IsPostAdress.typenr

Related

SQL Group By specific column with nullable

Let's say I have this data in my table A:
group_id
type
active
1
A
true
1
B
false
1
C
true
2
null
false
3
B
true
3
C
false
I want to create a query which return the A row if exists (without the type column), else return a row with active false.
For this specific table the result will be:
group_id
active
1
true
2
false
3
false
How can I do this ?
I'm assuming I have to use a GROUP BY but I can't find a way to do it.
Thank you
This is a classic row_number problem, generate a row number based on your ordering criteria, then select just the first row in each grouping.
declare #MyTable table (group_id int, [type] char(1), active bit);
insert into #MyTable (group_id, [type], active)
values
(1, 'A', 1),
(1, 'B', 0),
(1, 'C', 1),
(2, null, 0),
(3, 'B', 1),
(3, 'C', 0);
with cte as (
select *
, row_number() over (
partition by group_id
order by case when [type] = 'A' then 1 else 0 end desc, active asc
) rn
from #MyTable
)
select group_id, active
from cte
where rn = 1
order by group_id;
Returns:
group_id
active
1
1
2
0
3
0
Note: Providing the DDL+DML as I have shown makes it much easier for people to assist.
This should do it. We select all the distinct group_ids and then join our table back to that. There is an ISNULL function that will insert the 'false' when 'A' type records are not found.
DECLARE #tableA TABLE (
group_id int
, [type] nchar(1)
, active nvarchar(10)
);
INSERT INTO #tableA (group_id, [type], active)
VALUES
(1, 'A', 'true')
, (1,'B','false')
, (1,'C', 'false')
, (2, null, 'false')
, (3, 'B', 'true')
, (3, 'C', 'false')
;
SELECT
gid.group_id
, ISNULL(a.active,'false') as active
FROM (SELECT DISTINCT group_id FROM #tableA) as gid
LEFT OUTER JOIN #tableA as a
ON a.group_id = gid.group_id
AND a.type = 'A'

SQL Duplicates optimization

I have the following query:
Original query:
SELECT
cd1.cust_number_id, cd1.cust_number_id, cd1.First_Name, cd1.Last_Name
FROM #Customer_Data cd1
inner join #Customer_Data cd2 on
cd1.Cd_Id <> cd2.Cd_Id
and cd2.cust_number_id <> cd1.cust_number_id
and cd2.First_Name = cd1.First_Name
and cd2.Last_Name = cd1.Last_Name
inner join #Customer c1 on c1.Cust_id = cd1.cust_number_id
inner join #Customer c2 on c2.cust_id = cd2.cust_number_id
WHERE c1.cust_number <> c2.cust_number
I optimized it as follows, but there is an error in my optimization and I can't find it:
Optimized query:
SELECT cd1.cust_number_id, cd1.cust_number_id, cd1.First_Name,cd1.Last_Name
FROM (
SELECT cdResult.cust_number_id, cdResult.First_Name,cdResult.Last_Name, COUNT(*) OVER (PARTITION BY cdResult.First_Name, cdResult.Last_Name) as cnt_name_bday
FROM #Customer_Data cdResult
WHERE cdResult.First_Name IS NOT NULL
AND cdResult.Last_Name IS NOT NULL) AS cd1
WHERE cd1.cnt_name_bday > 1;
Test data:
DECLARE #Customer_Data TABLE
(
Cd_Id INT,
cust_number_id INT,
First_Name NVARCHAR(30),
Last_Name NVARCHAR(30)
)
INSERT #Customer_Data (Cd_Id,cust_number_id,First_Name,Last_Name)
VALUES (1, 22, N'Alex', N'Bor'),
(2, 22, N'Alex', N'Bor'),
(3, 23, N'Alex', N'Bor'),
(4, 24, N'Tom', N'Cruse'),
(5, 25, N'Tom', N'Cruse')
DECLARE #Customer TABLE
(
Cust_id INT,
Cust_number INT
)
INSERT #Customer (Cust_id, Cust_number)
VALUES (22, 022),
(23, 023),
(24, 024),
(25, 025)
The problem is that the original query returns 6 rows (duplicating the row). And optimized returns just duplicates, how to make the optimized query also duplicated the row?
I would suggest just using window functions:
SELECT CD.cud_customer_id
FROM (SELECT cd.*, COUNT(*) OVER (PARTITION BY cud_name, cud_birthday) as cnt_name_bday FROM dbo.customer_data cd
) cd
WHERE cnt_name_bday > 1;
Your query is finding duplicates for either name or birthday. You want duplicates with both at the same time.
You can use only one exists :
SELECT cd.cud_customer_id
FROM dbo.customer_data AS cd
WHERE EXISTS (SELECT 1
FROM dbo.customer_data AS c
WHERE c.cud_name = cd.cud_name AND c.cud_birthday = cd.cud_birthday AND c.cust_id <> cd.cud_customer_id
);

Insert multiple row different column value

This is my existing table
In this table, each user has their own respective data according to their Status. Each of the user will surely have Status 1.
Now, there are 3 Status to be stored for every user.
Was trying to make every user to have 3 Status, by inserting new row of user copying their Status 1 data, such that:
User Ali currently only have Status 1 and its data, so need insert a new
row Ali with Status 2 and copy along the data from Status 1, again,
insert a new row Ali with Status 3 and copy along the data from
Status 1.
User John currently only have Status 1 and 2, so need insert a new
row John with Status 3 and copy along the data from Status 1.
continue same pattern with other user
Expected result:
I would use CROSS JOIN and NOT EXISTS
with data as
(
select name,
column1,
column2
from your_table
where status = 1
), cross_join_data as
(
select d1.name, t.status, d1.column1, d1.column2
from data d1
cross join
(
select 1 status
union
select 2 status
union
select 3 status
) t
where not exists (
select 1
from your_table d2
where d2.name = d1.name and
d2.status = t.status
)
)
select *
from your_table
union all
select *
from cross_join_data
dbfiddle demo
This should work
with cte as (
select
[Name], coalesce(max(iif([Status]=1, [Column1], null)), max(iif([Status]=2, [Column1], null)), max(iif([Status]=3, [Column1], null))) col1
, coalesce(max(iif([Status]=1, [Column2], null)), max(iif([Status]=2, [Column2], null)), max(iif([Status]=3, [Column2], null))) col2
from
MyTable
group by [Name]
)
--insert into MyTable
select
cte.[Name], nums.n, cte.col1, cte.col2
from
cte
cross join (values (1),(2),(3)) nums(n)
left join MyTable on cte.[Name]=MyTable.[Name] and n=MyTable.[Status]
where
MyTable.[Status] is null
This works if data is not nullable
declare #table table (name varchar(10), status int, data int);
insert into #table values
('a', 1, 2)
, ('a', 2, 5)
, ('a', 3, 7)
, ('b', 1, 5)
, ('b', 2, 6)
, ('c', 1, 3)
select stats.status as statusStats
, tn.name as nameTN
, t.status as statusData, t.name, t.data
, ISNULL(t.data, t1.data) as 'fillInData'
from (values (1),(2),(3)) as stats(status)
cross join (select distinct name from #table) tn
left join #table t
on t.status = stats.status
and t.name = tn.name
join #table t1
on t1.name = tn.name
and t1.status = 1
order by tn.name, stats.status
Here is what I would do:
CREATE TABLE #existingtable (Name VARCHAR(50), Status INT, Column1 VARCHAR (10), Column2 VARCHAR(10));
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('Ali',1,'100','90');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('John',1,'20','200');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('John',2,'80','90');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('Ming',1,'54','345');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('Mei',1,'421','123');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('Mei',3,'24','344');
SELECT * FROM #existingtable;
WITH CTE (Name,Column1,Column2)
AS
(
SELECT DISTINCT NAME,COLUMN1,COLUMN2
FROM #existingtable
)
, CTE2 (NAME,Status,Column1,Column2)
AS
(
SELECT NAME,1 AS STATUS,COLUMN1,COLUMN2
FROM CTE
UNION
SELECT NAME,2 AS STATUS,COLUMN1,COLUMN2
FROM CTE
UNION
SELECT NAME,3 AS STATUS,COLUMN1,COLUMN2
FROM CTE
)
INSERT INTO #existingtable (Name,Status,Column1,Column2)
SELECT C.Name,C.Status,C.Column1,C.Column2
FROM CTE2 AS C
LEFT JOIN #existingtable AS E
ON C.NAME = E.Name
AND C.Status = E.Status
WHERE E.Status IS NULL
SELECT * FROM #existingtable
ORDER BY Name, status
This has 2 edits. Initial edit added a where clause to the CTE
Second edit added the values added by the OP

How to get the ID from the table which is not mention EndDate

How to get the name from the table which is not having EndDate
in the above pic i need to get D and G details from the table ,
( To understand mOre:
A, C,D,G are having end date, and A, C are again started, but D and G is not started, so from the query i need to get the name D and G
the code i used is not works for it
DECLARE #T AS TABLE
(
SubInventoryID int ,
SubInventoryName varchar(20),
RolesName varchar(20),
StartDate date,
EndDate date
)
INSERT INTO #T VALUES
(30,'RIF-Teller','Teller', '2016-12-27', '2017-01-23'),
(30,'RIF-Teller','Teller', '2016-12-08', NULL),
(30,'RIF-Teller','Teller', '2017-01-02', '2017-01-05'),
(31,'RIF-Teller','Teller', '2017-01-05', NULL),
(24,'MHQ-Teller','Teller', '2016-09-20', '2017-01-23'),
(24,'MHQ-Teller','Teller', '2016-08-01', '2017-01-05'),
(24,'MHQ-Teller','Teller', '2017-01-05', NULL)
Query
SELECT UP.SubInventoryID,S.SubInventoryName SubInventoryName,RolesName,UP.StartDate StartDate,
UP.EndDate EndDate , case when UP.EndDate IS null then 'Occupied' else 'Closed' End As Vacancy
FROM [View_Alx_UserPosition] UP
Inner join ALX_Branches B ON B.BranchID= UP.BranchID
Inner join ALX_SubInventories S ON S.SubInventoryID=UP.SubInventoryID WHERE UP.RolesName Like '%Teller%'
union
SELECT distinct(UP.SubInventoryID),S.SubInventoryName SubInventoryName, '' FullName, '' RolesName,NUll StartDate,
NUll EndDate,'Free' as vacancy
FROM [View_Alx_UserPosition] UP
Inner join ALX_Branches B ON B.BranchID= UP.BranchID
Inner join ALX_SubInventories S ON S.SubInventoryID=UP.SubInventoryID
WHERE UP.EndDate IS NOT NULL ANd UP.RolesName Like '%Teller%'
AND NOT EXISTS
(
SELECT 1
FROM [View_Alx_UserPosition] UP1
WHERE UP1.SubInventoryID = UP.SubInventoryID
AND UP1.StartDate >= UP.EndDate
-- AND UP1.EndDate IS NOT NULL
)
Update
Create and populate sample table (Please save us this step in your future questions)
DECLARE #T AS TABLE
(
ID int identity(1,1),
Name char(1),
StartDate date,
EndDate date
)
INSERT INTO #T VALUES
('A', '2016-04-04', '2017-04-03'),
('B', '2016-04-04', NULL),
('C', '2016-04-04', '2017-04-03'),
('D', '2016-04-04', '2017-04-03'),
('E', '2016-04-04', NULL),
('F', '2016-04-04', NULL),
('G', '2016-04-04', '2017-04-03'),
('C', '2017-04-03', NULL),
('A', '2017-04-03', NULL)
The query:
SELECT Name
FROM #T vu1
WHERE EndDate IS NOT NULL
AND NOT EXISTS
(
SELECT 1
FROM #T vu2
WHERE vu2.Name = vu1.Name
AND vu2.StartDate >= vu1.EndDate
)
Results:
Name
D
G
First version
Assuming I understand the question, this should do the trick:
SELECT Name
FROM View_User vu1
WHERE EndDate IS NOT NULL
AND NOT EXISTS
(
SELECT 1
FROM View_User vu2
WHERE vu2.Name = vu1.Name
AND vu2.StartDate >= vu1.EndDate
AND vu2.EndDate IS NOT NULL
)

SQL update one single row table with data from another

I have two tables. The first one with all movements in twelve months and the second one with claims registered in the same period of time. When I run the following query from the first table I've got 10 records. Of course, there are other records with a different number of movements (e.g.: 7, 23, 2 movements):
select t.cod_suc
,t.cod_ramo_comercial
,t.Poliza
,t.Item
,t.id_pv
from temp_portafolio_personal_accidents as t
where t.cod_suc = 2
and t.cod_ramo_comercial = 46
and t.Poliza = 50283
and t.Item = 1
and t.id_pv = 788383;
With the second query, for the second table, I have the following results:
select c.cod_suc
,c.cod_ramo_comercial
,c.[No. Policy]
,c.Item
,c.[ID Incident]
,max(c.id_pv) as id_pv
,count(distinct [No. Incident]) as 'Conteo R12'
from #claims as c
where c.[ID Incident] = 343632
group by c.cod_suc
,c.cod_ramo_comercial
,c.[No. Policy]
,c.Item
,c.[ID Incident];
Now, I need to update the first table but only one record. I'm using the following query, but all records are being updated. When I sum results I have 10 but is just one claim, as the second query shows.
update p
set [No. Siniestros R12] = b.[Conteo R12]
from temp_portafolio_personal_accidents p
left join
(select c.cod_suc
,c.cod_ramo_comercial
,c.[No. Policy]
,c.Item
,c.[ID Incident]
,max(c.id_pv) as id_pv
,count(distinct [No. Incident]) as 'Conteo R12'
from
#claims as c
where c.[ID Incident] = 343632
group by c.cod_suc
,c.cod_ramo_comercial
,c.[No. Policy]
,c.Item
,c.[ID Incident]
) b
on p.id_pv = b.id_pv
and p.cod_suc = b.cod_suc
and p.cod_ramo_comercial = b.cod_ramo_comercial
and p.Poliza = b.[No. Policy]
and p.Item = b.Item
where p.id_pv = 788383;
You can use a CTE with a ROW_NUMBER() function to do this. Simple example:
DECLARE #TABLE AS TABLE (Testing INT, Testing2 VARCHAR(55), Testing3 BIT);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
WITH CTE AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY Testing) AS RowID
,Testing
,Testing2
,Testing3
FROM #TABLE
)
UPDATE CTE
SET Testing = 2, Testing2 = '2', Testing3 = 0
WHERE RowID = 1
;
SELECT * FROM #TABLE
;