SELECT table name that is inside UNION - tsql

I have two same tables.
I need to union them in such way:
SELECT f1,f2, xxx
FROM
(SELECT *
FROM tbl1
UNION ALL
SELECT *
FROM tbl2)
where xxx would query for a table name, where f1 and f2 fields are taken from.
Example output:
123 345 'tbl1' -- this rows are from the first table
121 345 'tbl1'
121 345 'tbl1'
123 345 'tbl1'
124 345 'tbl1'
125 345 'tbl2' -- this rows are from the second table
127 345 'tbl2'
Thank you in advance.

SELECT f1,f2, xxx
FROM
(SELECT *, 'tbl1' as xxx
FROM tbl1
UNION ALL
SELECT *, 'tbl2' as xxx
FROM tbl2)

Related

SQL Server CTE and recursion example misunderstanding

Could someone help me with cte expresion? I have a table:
old_card
new_card
dt
111
555
2020-01-09
222
223
2020-02-10
333
334
2020-03-11
444
222
2020-04-12
555
666
2020-05-12
666
777
2020-06-13
777
888
2020-07-14
888
0
2020-08-15
999
333
2020-09-16
223
111
2020-10-16
I need to get all the changes of old_card to a new_card, since old_card number 111 to a new_card number 0. So I must get 5 records from this table having only a new_card = 0 as input parameter
old_card
new_card
dt
111
555
2020-01-09
555
666
2020-05-12
666
777
2020-06-13
777
888
2020-07-14
888
0
2020-08-15
I think of to do it using cte, but I get all the records from the source table and can't understand why. Here is my cte:
;with cte as(
select
old_card,
new_card,
dt
from
cards_transfer
where
new_card = 0
union all
select
t1.old_card,
t1.new_card,
t1.dt
from
cards_transfer t1
inner join
cte on cte.old_card = t1.new_card)
But I get 8 rows instead. Can someone tell me please what I did wrong?
You said you wanted from 111 onwards. So you need to add that "stop" condition
where cte.old_card <> 111
;with cte as(
select
old_card,
new_card,
dt
from
cards_transfer
where
new_card = 0
union all
select
t1.old_card,
t1.new_card,
t1.dt
from
cards_transfer t1
inner join
cte on cte.old_card = t1.new_card
where cte.old_card <> 111
)

selecting out duplicate records within the same table column and list them out

I've searched but so far don't find answer fits my situation.
How do you write select statement to selecting out duplicate records within the same table column and list them (so not group by it)??
example: to find duplicates for contract_id column and list them out
ID contract_id Sales1 Sales2
1 12345 100 200
2 54321 300 674
3 12345 343 435
4 09876 125 654
5 54321 374 233
6 22334 543 335
Result should look like this with order by contract_id as well:
ID contract_id Sales1 Sales2
1 12345 100 200
3 12345 343 435
2 54321 300 674
5 54321 374 233
You could use a subquery on the count >1
select * from my_table
where contract_id in (
select contract_id
from my_table
group by contract_id
having count(*) > 1
)

results mismatched when retrieved dates from column of type character varying

I have two tables,i want to get the min and max date stored in table1 cfrange column which is of type character varying.
table1 and table2 is mapped using sid. i want to get the max and min date range when compared with sid of table2.
table1:
sid cfrange
100 3390
101 8000
102 5/11/2010
103 11/12/2016
104 01/03/2016
105 4000
106 4000
107 03/12/2017
108 03/11/2016
109 4/04/2018
110 10/12/2016
table2:
sid description
102 success
103 success
104 Proceeding
107 success
108 success
I tried as below but its not giving the correct min and max value.Please advice.
select max(t1.cfrange),min(t1.cfrange) from table1 t1,table2 t2 where t1.sid=t2.sid;
You should join two tables and cast cfrange as a date and cross your fingers. (May be you must format it as a date before to cast it).
create table table1 (sid int, cfrange varchar(30));
insert into table1 values
(100, '3390'),
(101, '8000'),
(102, '5/11/2010'),
(103, '11/12/2016'),
(104, '01/03/2016'),
(105, '4000'),
(106, '4000'),
(107, '03/12/2017'),
(108, '03/11/2016'),
(109, '4/04/2018'),
(110, '10/12/2016');
create table table2 (sid int, description varchar(30));
insert into table2 values
(102, 'success'),
(103, 'success'),
(104, 'Proceeding'),
(107, 'success'),
(108, 'success');
select 'Min' as caption, min(cfrange) as value
from (select table1.sid, table1.cfrange::date
from table1
inner join table2
on table1.sid = table2.sid) tt
UNION ALL
select 'Max' as caption, max(cfrange) as value
from (select table1.sid, table1.cfrange::date
from table1
inner join table2
on table1.sid = table2.sid) tt;
caption | value
:------ | :---------
Min | 2010-11-05
Max | 2017-12-03
dbfiddle here

Hi Folks replace the null values with max value in the table and add 1 to the max value

Can any one help me on this
my source table is like this
col1
-----
123
456
---
---
459
---
461
but i want target like this
col1
-----
123
456
457
458
459
460
461
Assuming your table name is ex contain a primary id number datatypes and col1 number datatypes.
select
nvl(col1,
nvl(
(select col1+1 from ex i where i.id = o.id-1),
(select col1+2 from ex i where i.id = o.id-2))
) from ex o;
If you notice there's a pattern in the sql. You can refactor that to a function. To see an example output here's a sqlfiddle.

T-SQL: finding rows in a different table without joins

I have two tables, I'll call TableA and TableB
TableA:
StartNumber EndNumber Country
1 10 USA
11 20 USA
21 30 Canada
31 40 France
41 50 France
51 60 Germany
TableB:
SomeNumber
5
15
55
22
35
46
49
For each number in TableB, I want to find the corresponding row in TableA where the number is between the StartNumber and EndNumber and return the name of the country. I then want to group these results on the country column and return the number of times each country appears. So the results would look like this:
Country Occurrences
USA 2
Germany 1
Canada 1
France 3
Not sure how to do this.
Here the query.
Select A.Country, count(*) as Occurrences
from
tableA A
inner join
tableB B
on B.someNumber between a.startnumber and b.endnumber
group by A.country
This should do the trick (but does use a join):
declare #TableA table (StartNumber int, EndNumber int, Country varchar(16));
insert into #TableA (StartNumber, EndNumber, Country)
select 1, 10, 'USA' union
select 11, 20, 'USA' union
select 21, 30, 'Canada' union
select 31, 40, 'France' union
select 41, 50, 'France' union
select 51, 60, 'Germany';
declare #TableB table (SomeNumber int);
insert into #TableB (SomeNumber)
select 5 union
select 15 union
select 55 union
select 22 union
select 35 union
select 46 union
select 49;
select
a.Country, count(*) Occurrences
from
#TableA a inner join
#TableB b on b.SomeNumber between a.StartNumber and a.EndNumber
group by
a.Country;