How to get Distinct Records from Temp table to Sql one database table - sql

i have temp table named "#Test" which have columns "T1", "T2", "T3" with data.
I have database table named "TestTbl" which have same columns.
I want to insert data from #Test table to TestTbl with distinct records of T1 column.
Do you have any idea how to insert distinct records in TestTbl table?

You Can Try Like this....
INSERT INTO TestTbl (T1,T2,T3) SELECT T1,T2,T3 from
(
Select Row_Number() over(Partition By T1 order By T1) as row,* from #Test
) a
where a.row=1;

INSERT INTO TestTbl (T1,T2,T3)
SELECT Distinct(T1), T2, T3 FROM #Test
EDIT After further explanation
INSERT INTO TestTbl
( T1 ,
T2 ,
T3
)
SELECT T1 ,
T2 ,
T3
FROM ( SELECT T1 ,
T2 ,
T3 ,
Row_Number() OVER ( PARTITION BY T1 ORDER BY T1) AS record
-- you need to select the relevant clause here for the order
-- do you want first or latest record?
FROM #Test
) tmp
WHERE tmp.record = 1 ;

Get distinct records
SELECT DISTINCT column_name,column_name
FROM table_name
Insert records
INSERT INTO table_name (column1,column2,column3,...)
VALUES (value1,value2,value3,...)

Related

SQL - return differences between rows (in two different tables) but ONLY if row ID exists in both tables

I have two tables that contain two potential differences which I'm trying to pick up on - rows that exist only in one of the tables, and rows that exist in both (sharing a common ID) but having different values for one of the columns (columns are exactly the same in both tables).
CREATE TABLE "MyTable1" (ID INTEGER, FIRST_NAME TEXT, DOB DATE);
INSERT INTO MyTable1 VALUES (1, "Tom", "01-02-18");
INSERT INTO MyTable1 VALUES (2, "Dick", "02-02-18");
INSERT INTO MyTable1 VALUES (3, "Larry", "03-02-18");
INSERT INTO MyTable1 VALUES (4, "Jebroni", "04-02-18");
CREATE TABLE "MyTable2" (ID INTEGER, FIRST_NAME TEXT, DOB DATE);
INSERT INTO MyTable2 VALUES (1, "Tom", "01-02-18");
INSERT INTO MyTable2 VALUES (2, "Dick", "02-02-18");
INSERT INTO MyTable2 VALUES (3, "Barry", "03-02-18");
I can return IDs in MyTable1 not present in MyTable2:
SELECT MyTable1.*
FROM MyTable1
WHERE MyTable1.ID NOT IN (SELECT MyTable2.ID FROM MyTable2)
Returns what I'm after:
ID FIRST_NAME DOB
"4" "Jebroni" "04-02-18"
For the second part I want to compare values of each column for rows sharing a common ID.
SELECT 'TABLE1' AS SRC, MyTable1.*
FROM (
SELECT * FROM MyTable1
EXCEPT
SELECT * FROM MyTable2
) AS MyTable1
UNION ALL
SELECT 'TABLE2' AS SRC, MyTable2.*
FROM (
SELECT * FROM MyTable2
EXCEPT
SELECT * FROM MyTable1
) AS MyTable2
This returns more than what I'm after - rows that exist in one table and not the other:
SRC ID FIRST_NAME DOB
"TABLE1" "3" "Larry" "03-02-18"
"TABLE1" "4" "Jebroni" "04-02-18"
"TABLE2" "3" "Barry" "03-02-18"
How should I tweak my last query so that the result is instead:
SRC ID FIRST_NAME DOB
"TABLE1" "3" "Larry" "03-02-18"
"TABLE2" "3" "Barry" "03-02-18"
I.e. restrict what's returns on the basis of the ID being present in both tables?
Restrict the first set of rows to those with a matching ID in the other table:
SELECT 'TABLE1' AS SRC, *
FROM (
SELECT * FROM MyTable1 WHERE ID IN (SELECT ID FROM MyTable2)
EXCEPT -------------------------------------
SELECT * FROM MyTable2
)
UNION ALL
SELECT 'TABLE2' AS SRC, *
FROM (
SELECT * FROM MyTable2 WHERE ID IN (SELECT ID FROM MyTable1)
EXCEPT -------------------------------------
SELECT * FROM MyTable1
);
I would just use join:
select *
from MyTable1 t1 join
MyTable2 t2
on t1.id = t2.id
where t1.firstname <> t2.firstname or t1.dob <> t2.dob;
I don't think set-based operations will do exactly what you want. But you can add to your query:
where id in (select id from mytable1 t1
intersect
select id from mytable2 t2
)
This will limit results to ids in both tables and you don't have to list out the rest of the columns.

How to add the sum of the 'sum of the two tables?'

I created Tables T1 and T2. I managed to add their sum, but I can't seem to add the sum of the T1 and T2 together (10+12 = 22) by adding a sum() in the beginning of the code.
CREATE TABLE T1(kW int)
CREATE TABLE T2(kW int)
SELECT T1C1, T2C1
FROM
( select SUM(Kw) T1C1 FROM T1 ) A
CROSS JOIN
( select SUM(Kw) T2C1 FROM T2 ) B
BEGIN
INSERT INTO T1 VALUES ('4');
INSERT INTO T1 VALUES ('1');
INSERT INTO T1 VALUES ('5');
INSERT INTO T2 VALUES ('7');
INSERT INTO T2 VALUES ('2');
INSERT INTO T2 VALUES ('3');
END
You should use union all to create a "virtual" column from the columns in the two tables:
SELECT SUM(kw)
FROM (SELECT kw FROM t1
UNION ALL
SELECT kw FROM t2) t
Try using a stored procedure. Doing so you will be able to store the sum of each table on a separated variable and then return the SUM of those two variables.
You can also make a UNION ALL and SUM the column you want. Notice that you should a UNION ALL to avoid eliminating duplicated values.
Another approach is to add the results of the two subqueries directly, using the built-in dummy table dual as the main driving table:
select ( select SUM(Kw) FROM T1 )
+ ( select SUM(Kw) FROM T2 ) as total
from dual;
TOTAL
----------
22

INSERT INTO SELECT query that includes the GETDATE() function

I have an INSERT INTO SELECT statement (below) that works fine but I can't figure out how to also populate a datetime field in tbl named rundate.
In other words, I want: INSERT INTO tbl (title,invnum,rundate) where rundate will get the value returned by the GETDATE() function.
INSERT INTO tbl (title,invnum)
SELECT #title,t1.invnum FROM #InvenNums t1 WHERE NOT EXISTS (
SELECT title,invnum FROM tbl t2
WHERE t2.invnum=t1.invnum AND t2.title=#title)
Is this what you want?
INSERT INTO tbl (title, invnum, rundate)
SELECT #title, t1.invnum, GETDATE()
FROM #InvenNums t1
WHERE NOT EXISTS (SELECT 1 FROM tbl t2 WHERE t2.invnum = t1.invnum AND t2.title = #title);

Insert lost data to the table

I have two tables, which have two common column 'StationID'.
Create table t1(ID int, StationID bigint)
insert into t1 values
(0,1111),
(1,2222),
(2,34),
(3,456209),
(56,78979879),
(512,546)
go
Create table t2(StationID bigint, Descr varchar(50))
insert into t2 values
(-1,'test-1'),
(0,'test0'),
(1,'test1'),
(2,'test2'),
(5001,'dummy'),
(5002,'dummy'),
(6001,'dummy')
go
Now we notice that not every t1.StationID is in t2.StationID. Run the script can prove it.
select distinct StationID from t1 as A
where not exists
(select * from t2 as B where B.StationID =A.StationID)
The result is:
StationID
34
546
1111
2222
456209
78979879
Now I want to fill t2 with the lost StationID above, the column Descr can be any dummy data.
My real case has thousands records, how to use script to implement it?
insert into t2 (StationID, Descr)
select distinct StationID, 'dummy'
from t1 as A
where not exists
(select * from t2 as B where B.StationID =A.StationID)
INSERT INTO
t2
SELECT DISTINCT
stationid, 'dummy'
FROM
t1
WHERE
stationid NOT IN (SELECT stationid FROM t2)
(As an alternative to the others).

How to get the closest dates in Oracle sql

For example, I have 2 time tables:
T1
id time
1 18:12:02
2 18:46:57
3 17:49:44
4 12:19:24
5 11:00:01
6 17:12:45
and T2
id time
1 18:13:02
2 17:46:57
I need to get time from T1 that are the closest to time from T2. There is no relationship between this tables.
It should be something like this:
select T1.calldatetime
from T1, T2
where T1.calldatetime between
T2.calldatetime-(
select MIN(ABS(T2.calldatetime-T1.calldatetime))
from T2, T1)
and
T2.calldatetime+(
select MIN(ABS(T2.calldatetime-T1.calldatetime))
from T2, T1)
But I can't get it. Any suggestions?
You only have to use a single Cartesian join to solve you problem unlike the other solutions, which use multiple. I assume time is stored as a VARCHAR2. If it is stored as a date then you can remove the TO_DATE functions. If it is stored as a date (I would highly recommend this), you will have to remove the date portions
I've made it slightly verbose so it's obvious what's going on.
select *
from ( select id, tm
, rank() over ( partition by t2id order by difference asc ) as rnk
from ( select t1.*, t2.id as t2id
, abs( to_date(t1.tm, 'hh24:mi:ss')
- to_date(t2.tm, 'hh24:mi:ss')) as difference
from t1
cross join t2
) a
)
where rnk = 1
Basically, this works out the absolute difference between every time in T1 and T2 then picks the smallest difference by T2 ID; returning the data from T1.
Here it is in SQL Fiddle format.
The less pretty (but shorter) format is:
select *
from ( select t1.*
, rank() over ( partition by t2.id
order by abs(to_date(t1.tm, 'hh24:mi:ss')
- to_date(t2.tm, 'hh24:mi:ss'))
) as rnk
from t1
cross join t2
) a
where rnk = 1
I believe this is the query you are looking for:
CREATE TABLE t1(id INTEGER, time DATE);
CREATE TABLE t2(id INTEGER, time DATE);
INSERT INTO t1 VALUES (1, TO_DATE ('18:12:02', 'HH24:MI:SS'));
INSERT INTO t1 VALUES (2, TO_DATE ('18:46:57', 'HH24:MI:SS'));
INSERT INTO t1 VALUES (3, TO_DATE ('17:49:44', 'HH24:MI:SS'));
INSERT INTO t1 VALUES (4, TO_DATE ('12:19:24', 'HH24:MI:SS'));
INSERT INTO t1 VALUES (5, TO_DATE ('11:00:01', 'HH24:MI:SS'));
INSERT INTO t1 VALUES (6, TO_DATE ('17:12:45', 'HH24:MI:SS'));
INSERT INTO t2 VALUES (1, TO_DATE ('18:13:02', 'HH24:MI:SS'));
INSERT INTO t2 VALUES (2, TO_DATE ('17:46:57', 'HH24:MI:SS'));
SELECT t1.*, t2.*
FROM t1, t2,
( SELECT t2.id, MIN (ABS (t2.time - t1.time)) diff
FROM t1, t2
GROUP BY t2.id) b
WHERE ABS (t2.time - t1.time) = b.diff;
Make sure that the time columns have the same date part, because the t2.time - t1.time part won't work otherwise.
EDIT: Thanks for the accept, but Ben's answer below is better. It uses Oracle analytic functions and will perform much better.
This one here selects that row(s) from T1, which has/have the smallest distance to any in T2:
select T1.id, T1.calldatetime from T1, T2
where ABS(T2.calldatetime-T1.calldatetime)
=( select MIN(ABS(T2.calldatetime-T1.calldatetime))from T1, T2);
(tested it with mysql, hope you dont get an ORA from that)
Edit: according to the last comment, it should be like that:
drop table t1;
drop table t2;
create table t1(id int, t time);
create table t2(id int, t time);
insert into t1 values (1, '18:12:02');
insert into t1 values (2, '18:46:57');
insert into t1 values (3, '17:49:44');
insert into t1 values (4, '12:19:24');
insert into t1 values (5, '11:00:01');
insert into t1 values (6, '17:12:45');
insert into t2 values (1, '18:13:02');
insert into t2 values (2, '17:46:57');
select ot2.id, ot2.t, ot1.id, ot1.t from t2 ot2, t1 ot1
where ABS(ot2.t-ot1.t)=
(select min(abs(t2.t-t1.t)) from t1, t2 where t2.id=ot2.id)
Produces:
id t id t
1 18:13:02 1 18:12:02
2 17:46:57 3 17:49:44
Another one way of using analytic functions.
May be strange :)
select id, time,
case
when to_date(time, 'hh24:mi:ss') - to_date(lag_time, 'hh24:mi:ss') < to_date(lead_time, 'hh24:mi:ss') - to_date(time, 'hh24:mi:ss')
then lag_time
else lead_time
end closest_time
from (
select id, tbl,
LAG(time, 1, null) OVER (ORDER BY time) lag_time,
time,
LEAD(time, 1, null) OVER (ORDER BY time) lead_time
from
(
select id, time, 1 tbl from t1
union all
select id, time, 2 tbl from t2
)
)
where tbl = 2
To SQLFiddle... and beyond!
Try this query its little lengthy, I will try to optimize it
select * from t1
where id in (
select id1 from
(select id1,id2,
rank() over (partition by id2 order by diff) rnk
from
(select distinct t1.id id1,t2.id id2,
round(min(abs(to_date(t1.time,'HH24:MI:SS') - to_date(t2.time,'HH24:MI:SS'))),2) diff
from
t1,t2
group by t1.id,t2.id) )
where rnk = 1);