One of my users ran the following code
set nocount on;
with R0 as
(
select 1 as f1
union all
select 1
union all
select 1
union all
select 1
union all
select 1
),
R1 as (select a.f1 as f1 from R0 a cross join R0 b),
R2 as (select a.f1 as f1 from R1 a cross join R1 b),
R3 as (select a.f1 as f1 from R2 a cross join R2 b)
select top 350000 f1
into t1
from R3
go
set nocount off
declare #v1 int = 12345
update a
set #v1 = a.f1 = #v1+1
from t1 a
GO
select * from t1 order by 1
drop table t1
In SQL Server 2014 he got the numbers sequentially; like this:
12346
12347
12348
But in SQL Server 2017, he gets the following results:
12346
12346
12346
12346
12346
12346
12346
12346
12346
12346
12347
12347
12347
etc
I thought this was because of IDENTITY_CACHE but turned that off with same results.
Also tried installing CU12 on an instance but same effect.
Any suggestions?
Related
I have a query that, in very simplified form, looks like this:
SELECT aa, bb, xx
FROM (VALUES ('a1', 'b1'), ('a2', 'b2')) as T1(aa, bb)
LEFT JOIN (
SELECT xx FROM (VALUES
('a1', 'y1'), ('x2', 'y2')) as T2(xx, yy)
) as T3 ON T1.aa = T3.xx ;
which executes to produce this:
aa | bb | xx
----+----+--------
a1 | b1 | a1
a2 | b2 | (NULL)
(2 rows)
In real life the column xx is defined using a case statement and alias:
SELECT
...,
(CASE WHEN rgr.age_years < 18 THEN '< 18'
WHEN rgr.age_years < 36 THEN '26-35'
WHEN rgr.age_years < 46 THEN '36-45'
WHEN rgr.age_years < 56 THEN '46-55'
WHEN rgr.age_years < 130 THEN '> 55' END)
as row_name,
...
FROM
(VALUES ('< 18'), ('26-35'), ('36-45'),
('46-55'), ('> 55'))
as prn(possible_row_name)
LEFT JOIN other_table rgr
ON prn.possible_row_name = ??row_name??
Obviously ??row_name?? is an alias and so is not available at the time I specify the join. But I've not found the right formulation.
The point is simply that I'm doing a select on table rgr and I want all the age tranches present, even if no entity satisfies that number.
You can create the column on the fly inside the table expression rgr, as in:
SELECT
...,
rgr.row_name,
...
FROM
(VALUES ('< 18'), ('26-35'), ('36-45'),
('46-55'), ('> 55'))
as prn(possible_row_name)
LEFT JOIN ( -- table expression rgr defined here
select t.*,
CASE WHEN rgr.age_years < 18 THEN '< 18'
WHEN rgr.age_years < 36 THEN '26-35'
WHEN rgr.age_years < 46 THEN '36-45'
WHEN rgr.age_years < 56 THEN '46-55'
WHEN rgr.age_years < 130 THEN '> 55' END
as row_name
from other_table t
) rgr ON prn.possible_row_name = rgr.row_name
I want to select the records that have a unique column combination in postgresql, however it doesn't seem to work with distinct as distinct only removes duplicates.
Example
ID A B
01 1 2
02 1 2
03 1 3
04 2 4
05 1 4
06 2 4
07 2 5
08 1 3
In this example row with ID 05 and 07 have unique combination AB, how can i get these records
SELECT ...
With NOT EXISTS:
select t.* from tablename t
where not exists (
select 1 from tablename
where id <> t.id and a = t.a and b = t.b
)
Or with COUNT() window function:
select t.id, t.a, t.b
from (
select *, count(id) over (partition by a, b) counter
from tablename
) t
where t.counter = 1
Or with aggregation:
select max(id) id, a, b
from tablename
group by a, b
having count(id) = 1
Or with a self LEFT join that excludes the matching rows:
select t.*
from tablename t left join tablename tt
on tt.id <> t.id and tt.a = t.a and tt.b = t.b
where tt.id is null
See the demo.
Results:
| id | a | b |
| --- | --- | --- |
| 05 | 1 | 4 |
| 07 | 2 | 5 |
I have two sql columns each with delimited data that I want to collate and combine into a single delimited column. The number of items in the column is variable for each row. However there will always be a matching number of items between the two columns of each row. For Example...
*******************************
ORIGINAL SQL TABLE
*******************************
value * unit
*******************************
4 ; 5 * mg ; kg
50 * mg
7.5 ; 325 * kg ; mg
100 ; 1.5 ; 50 * mg ; g ; mg
********************************
*********************************
DESIRED SQL RESULT
*********************************
value-unit
*********************************
4 mg; 5 kg
50 mg
7.5 kg; 325 mg
100 mg; 1.5 g; 50 mg
*********************************
How do I do this with T-SQL? I'm using SQL Server 2012
Using only common table expressions, we can get to the required results too, as below:-
First lets set up the data
declare #original table(
[value] varchar(250),
[unit] varchar(250)
)
insert into #original values
('4 ; 5','mg ; kg '),
('50','mg ' ),
('7.5 ; 325','kg ; mg ' ),
('100 ; 1.5 ; 50 ','mg ; g ; mg' )
Now, lets build the common table expressions:-
;with cte as (
select o.[value]+';' [value],o.[unit]+';' [unit],row_number() over (ORDER BY (Select 0)) [row] from #original o
),cte2 as (
select *
,1 [ValueStart],CHARINDEX(';',[value]) [ValueEnd]
,1 [UnitStart],CHARINDEX(';',[unit]) [UnitEnd]
from cte
),cte3 as (
select * from cte2
union all
select [value],[unit],[row]
,[ValueEnd]+1 [ValueStart],CHARINDEX(';',[value],[ValueEnd]+1) [ValueEnd]
,[UnitEnd]+1 [UnitStart],CHARINDEX(';',[unit],[UnitEnd]+1) [UnitEnd]
from cte3 where [UnitEnd]>0
),cte4 as (
select *,row_number() over (partition by [row] order by [row]) [subRow]
, rtrim(ltrim(substring([unit],[UnitStart],[UnitEnd]-[UnitStart]))) [subUnit]
, rtrim(ltrim(substring([value],[ValueStart],[ValueEnd]-[ValueStart]))) [subValue]
from cte3
where [UnitEnd]>0
),cte5 as (
select subRow,[row],[subValue],[subUnit],cast([subValue]+' '+[subUnit] as varchar(max)) [ValueUnit] from cte4 where subRow=1
union all
select cte4.subRow,cte4.[row],cte4.[subUnit],cte4.[subValue]
,cte5.[ValueUnit]+';'+ cte4.[subValue]+' '+cte4.[subUnit] [ValueUnit]
from cte4
inner join cte5 on (cte5.subRow+1)=cte4.subRow and cte5.[row]=cte4.[row]
),cte6 as (
select *,row_number() over (partition by [row] order by subRow desc) [selected] from cte5
)
select ValueUnit from cte6
where [selected]=1
order by [row]
Results will be as below:-
ValueUnit
============
4 mg;5 kg
50 mg
7.5 kg;325 mg
100 mg;1.5 g;50 mg
STRING_SPLIT is the most current solution. If you're not on 2016 or later and cannot set your db compatibility to that version or later, here is a more old fashioned approach using xml:
I added an Identity to your original table to have something to order by -
SELECT splitNumbers.splitNumber,
splitValues.splitValue,
splitNumbers.splitNumber + ' ' + splitValues.splitValue AS combined
FROM
(
SELECT --numbers,
LTRIM(RTRIM(m.n.value('.[1]', 'varchar(8000)'))) AS splitNumber,
ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM
(
SELECT id,
CAST('<XMLRoot><RowData>' + REPLACE(numbers, ' ; ', '</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS xmlNumbers
FROM #x
) fee
CROSS APPLY xmlNumbers.nodes('/XMLRoot/RowData') m(n)
) splitNumbers
INNER JOIN
(
SELECT LTRIM(RTRIM(m.v.value('.[1]', 'varchar(8000)'))) AS splitValue,
ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM
(
SELECT id,
CAST('<XMLRoot><RowData>' + REPLACE(units, ' ; ', '</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS xmlUnits
FROM #x
) fee
CROSS APPLY xmlUnits.nodes('/XMLRoot/RowData') m(v)
) splitValues
ON splitNumbers.rn = splitValues.rn;
This gives the following results:
================================
splitNumber splitValue combined
4 mg 4 mg
5 kg 5 kg
50 mg 50 mg
7.5 kg 7.5 kg
325 mg 325 mg
100 mg 100 mg
1.5 g 1.5 g
50 mg 50 mg
I have two table suppose table 'friendship' with column f1,f2 and 'people' with column p_id,p_name.
firendship:=>
f1 f2
--------
01 10
02 11
03 12
People:=>
p_id p_name
------------
01 Vijay
02 Ajay
03 Gaurav
10 Sunny
11 Amit
12 Sandeep
and i want result like this table
Result Table should be:=>
f1 f1_name f2 f2_name
------------------------
01 Vijay 10 Sunny
02 Ajay 11 Amit
03 Gaurav 12 Sandeep
i try with Union two tables but can't found accurate result
SELECT a.p_id f1, a.p_name f1_name, b.p_id f2, b.p_name f2_name FROM People a JOIN friendship f ON (f.f1 = a.p_id) JOIN People b ON (f.f2 = b.p_id)
You need Join for this
select f1, p.p_name as f1_name , f2, p1.p_name f2_name
from firendship as f
inner join People as p on f.f1=p.p_id
inner join People as p1 on f.f2=p1.p_id
I think this can solve your problem.
select a.f1, c.p_name, b.f2, c.p_name
(select * from tablea) as a,// which have f1 and f2 columns
(select * from tablea) as b,
(select * from people) as c
where a.f1=c.p_id and b.f2=c.p_id
Table1
sub-id ref-id Name
1 1 Project 1
2 1 Project 2
3 2 Project 3
4 2 Project 4
Table2
sub-id ref-id log_stamp Recepient log_type
----------------------------------------------------
1 1 06/06/2011 person A 1
1 1 06/14/2011 person B 2
1 1 06/16/2011 person C 2
1 1 06/17/2011 person D 3
2 1 06/18/2011 person E 2
2 1 06/19/2011 person F 2
3 2 06/20/2011 person G 1
4 2 06/23/2011 person H 3
Result
Name ref-id start_date Recepient latest_comment Recepient completion_date Receipient
Project1 1 06/06/2011 person A 06/19/2011 person F 06/17/2011 person D
Project3 2 06/20/2011 person G NULL NULL 06/23/2011 person H
log_type of 1 stands for start_date
log_type of 2 stands for latest_comment
log_type of 3 stands for completion_date
The Name of the project is just the name of the top-most name in the same group of ref-id
have tried this for now
;with T as (select
Table2.ref-id,
Table2.log_stamp,
Table2 log.log_type
when 1 then '1'
when 2 then '2'
when 3 then '3'
end as title
from
Submission sb inner join submission_log log on Table1.[sub-id] = Table2.[sub-id]
)
select * from T
pivot (
max(log_stamp)
for title IN ([1],[2],[3],[5],[6],[9],[11])
I was unable to do it as a pivot, I dont think it is possible as described
DECLARE #table1 TABLE (sub_id INT, ref_id INT, name VARCHAR(50))
INSERT #table1 VALUES (1, 1, 'Project 1')
INSERT #table1 VALUES (2, 1, 'Project 2')
INSERT #table1 VALUES (3, 2, 'Project 3' )
INSERT #table1 VALUES (4, 2, 'Project 4')
DECLARE #Table2 TABLE (sub_id INT, ref_id INT, log_stamp DATETIME, recepient VARCHAR(10), logtype INT)
INSERT #table2 VALUES(1,1,'06/06/2011','person A',1)
INSERT #table2 VALUES(1,1,'06/14/2011','person B',2)
INSERT #table2 VALUES(1,1,'06/16/2011','person C',2)
INSERT #table2 VALUES(1,1,'06/17/2011','person D',3)
INSERT #table2 VALUES(2,1,'06/18/2011','person E',2)
INSERT #table2 VALUES(2,1,'06/19/2011','person F',2)
INSERT #table2 VALUES(3,2,'06/20/2011','person G',1)
INSERT #table2 VALUES(3,2,'06/23/2011','person H',3)
;WITH a as (
SELECT RN = ROW_NUMBER() OVER (PARTITION BY t1.sub_id, t1.ref_id, t1.name, t2.logtype ORDER BY log_stamp DESC), t1.sub_id, t1.ref_id, t1.name, t2.Recepient , t2.logtype ,log_stamp
FROM #table1 t1 JOIN #table2 t2 ON t1.ref_id = t2.ref_id AND
t1.sub_id = t2.sub_id),
b as (SELECT * FROM a WHERE RN = 1)
SELECT b1.name, b1.ref_id,b1.log_stamp start_date , b1.Recepient, b2.log_stamp latest_comment , b2.Recepient, b3.log_stamp completion_date , b3.Recepient
FROM b b1
LEFT JOIN b b2 ON b1.sub_id=b2.sub_id AND b1.ref_id = b2.ref_id AND b2.logtype = 2
LEFT JOIN b b3 ON b1.sub_id=b3.sub_id AND b1.ref_id = b3.ref_id AND b3.logtype = 3
WHERE b1.logtype = 1
Result:
name ref_id start_date Recepient latest_comment Recepient completion_date Recepient
------------ ----------- ----------------------- ---------- ----------------------- ---------- ----------------------- ----------
Project 1 1 2011-06-06 00:00:00.000 person A 2011-06-16 00:00:00.000 person C 2011-06-17 00:00:00.000 person D
Project 3 2 2011-06-20 00:00:00.000 person G NULL NULL 2011-06-23 00:00:00.000 person H