Merge 2 tables into 1 SQL Server - sql

This is my current table:
Sales Table
OrderID Customer_ID Customer_Name
1 12 Bob
2 18 Ben
3 11 Harry
OrderID is the primary key
I have a temporary table Temp1:
Order_CreateDate Order_ReturnDate
20051102 20051104
20051103 20051108
20051104 20051105
I want to change the dates YYYYMMDD in Temp1 table, to YYYY-MM-DD, and move it to table, this code below does not work if I insert straight into Sales Table as it displays error saying:
Cannot insert the value NULL into column 'Order_ID', table 'car_rental.dbo.DataInCentralDatabase2'; column does not allow nulls. INSERT fails
However if I test it out by outputting to another temporary table, temp2, it works.
INSERT INTO [dbo].[sales]([Order_CreateDate])
SELECT
CONVERT(date,Order_CreateDate,111) AS Order_CreateDate
FROM dbo.temp1
But running this code two times for temp2 table (for the two converted columns) has the following result:
Order_CreateDate Order_ReturnDate
2005-11-02
2005-11-03
2005-11-04
NULL 2005-11-04
NULL 2005-11-08
NULL 2005-11-05
I know this question is extremely confusing, but as the end result I want it to become like this:
OrderID Customer_ID Customer_Name Order_CreateDate Order_ReturnDate
1 12 Bob 2005-11-02 2005-11-04
2 18 Ben 2005-11-03 2005-11-08
3 11 Harry 2005-11-04 2005-11-05
Any ideas on how to tackle this?

You need another column in Temp1 table as
OrderID Order_CreateDate Order_ReturnDate
1 20051102 20051104
2 20051103 20051108
3 20051104 20051105
Use Update query and not Insert query
UPDATE a set
Order_CreateDate=CONVERT(datetime,b.Order_CreateDate,111),
Order_ReturnDate=CONVERT(datetime,b.Order_ReturnDate,111)
from [dbo].[sales] a join [dbo].[Temp1] b on a.OrderID = b.OrderID

At the first, you should get an updated version of temp1 like this:
select
CONVERT(date,Order_CreateDate,111) as Order_CreateDate,
CONVERT(date,Order_ReturnDate,111) as Order_ReturnDate,
OrderID
into #temp2
from temp1
then, update your main table with join on temp1, like this:
update s
s.Order_CreateDate = t.Order_CreateDate,
s.Order_ReturnDate = t.Order_ReturnDate
from sales s
inner join #temp2 t
on s.OrderID = t.OrderID

Related

Returning value for all rows with same key, based on a single value

Is it possible to write a SQL script to create a table, which returns a single value from a table, based on an identifier for all connected rows?
For me to explain better, here's how the data looks like:
ID
Value
QuestionID
QuestionText
1
Jim Andersson
1
Name
1
Q894556
2
Order Number
1
21-03-2022
3
Date
...
...
...
...
I would like to be able to pinpoint both the Name and the Order Number for 2 new columns like below, which should be returned for all rows connected to ID = 1:
ID
Value
QuestionID
QuestionText
Name
Order Number
1
Jim Andersson
1
Name
Jim Andersson
Q894556
1
Q894556
2
Order Number
Jim Andersson
Q894556
1
21-03-2022
3
Date
Jim Andersson
Q894556
...
...
...
...
...
...
One way of doing it is joining table on itself given that the granulation of the output table should be the same as input table.
--create table for demonstration
create or replace TEMPORARY table test1.dummy (
ID int,
Value text,
questionID int,
questionText varchar);
--populate table with given data
INSERT INTO dummy values
(1, 'Jim Andersson',1, 'Name'),
(1, 'Q894556',2,'Order Number'),
(1, '21-03-2022',3,'Date');
The idea here is that we just need to limit extra tables given the value you want to add. And since we're joining on itself we can do this using INNER JOIN since it's faster. However, if you're unsure that batch of records will all contain Name, Order Number and date you could also do this using LEFT JOIN and have those values empty.
SELECT d1.*, d2.value AS NAME, d3.value AS Order_number
FROM dummy d1
inner JOIN dummy d2 ON d1.id = d2.id AND d2.questionText = 'Name'
inner JOIN dummy d3 ON d1.id = d3.id AND d3.questionText = 'Order Number';
Now all you need to do is use this query or create new table and fill it with given query.

SQL Select Where Opposite Match Does Not Exist

Trying to compare between two columns and check if there are no records that exist with the reversal between those two columns. Other Words looking for instances where 1-> 3 exists but 3->1 does not exist. If 1->2 and 2->1 exists we will still consider 1 to be part of the results.
Table = Betweens
start_id | end_id
1 | 2
2 | 1
1 | 3
1 would be added since it is a start to an end with no opposite present of 3,1. Though it did not get added until the 3rd entry since 1 and 2 had an opposite.
So, eventually it will just return names where the reversal does not exist.
I then want to join another table where the number from the previous problem has its name installed on it.
Table = Names
id | name
1 | Mars
2 | Earth
3 | Jupiter
So results will just be the names of those that don't have an opposite.
You can use a not exists condition:
select t1.start_id, t1.end_id
from the_table t1
where not exists (select *
from the_table t2
where t2.end_id = t1.start_id
and t2.start_id = t1.end_id);
I'm not sure about your data volume, so with your ask, below query will supply desired result for you in Sql Server.
create table TableBetweens
(start_id INT,
end_id INT
)
INSERT INTO TableBetweens VALUES(1,2)
INSERT INTO TableBetweens VALUES(2,1)
INSERT INTO TableBetweens VALUES(1,3)
create table TableNames
(id INT,
NAME VARCHAR(50)
)
INSERT INTO TableNames VALUES(1,'Mars')
INSERT INTO TableNames VALUES(2,'Earth')
INSERT INTO TableNames VALUES(3,'Jupiter')
SELECT *
FROM TableNames c
WHERE c.id IN (
SELECT nameid1.nameid
FROM (SELECT a.start_id, a.end_id
FROM TableBetweens a
LEFT JOIN TableBetweens b
ON CONCAT(a.start_id,a.end_id) = CONCAT(b.end_id,b.start_id)
WHERE b.end_id IS NULL
AND b.start_id IS NULL) filterData
UNPIVOT
(
nameid
FOR id IN (filterData.start_id,filterData.end_id)
) AS nameid1
)

Inserting into a table using the result of a MINUS subquery

I'm trying to insert the MINUS values from two tables (sample data) on ORACLE. I can insert all rows but I can't get it to work with the rows that are missing in the other table:
Sample Data:
SALES TABLE SALES2 TABLE S_DETAILS TABLE
=================== =================== ==================
ID_SALE|DATE_SALE ID_SALE|DATE_SALE ID_SALE|SALE_DETAILS
100 |12/12/2010 100 |12/12/2010 100 |SHIPPED
101 |5/10/2011 101 |5/10/2011 101 |WAITING
102 |10/9/2012 102 |SHIPPED
103 |5/10/2011 103 |PROCESSING
My Code:
INSERT INTO SALES_RESUME(ID_SALE,DATE_SALE,TOTAL_SALE,SALE_DETAILS)
SELECT A.ID_SALE,A.DATE_SALE,B.TOTAL_SALE,B.SALE_DETAILS
FROM SALES A
JOIN S_DETAILS B ON A.ID_SALE = B.ID_SALE
WHERE A.ID_SALE IN (SELECT ID_SALE FROM SALES
MINUS
SELECT ID_SALE FROM SALES2);
I want to insert rows into SALES_RESUME when the ID_SALE is in the resulting MINUS subquery, inserting:
SALES_RESUME
==============================
ID_SALE|DATE_SALE|SALE_DETAILS
102 |10/9/2012|SHIPPED
103 |5/10/2011|PROCESSING
Thanks in advance
Your query would appear to do what you want. But why not just write this?
WHERE A.ID_SALE NOT IN (SELECT ID_SALE FROM SALES2 WHERE ID_SALE IS NOT NULL); -- assuming SALES2.ID_SALE is never NULL
You already know that ID_SALE is in the first table.
If I got it, I think this query will work
SELECT A.ID_SALE,A.DATE_SALE,B.TOTAL_SALE,B.SALE_DETAILS
FROM ((select id_sale,DATE_SALE from SALES) minus (select id_sale,DATE_SALE from SALES2)) A
JOIN S_DETAILS B on A.id = B.id

Insert value from three tables into an empty table

I need to select FirstName, LastName, deliver_date, order_id, total_price from table 1, table 2, table 3 according to id and order_id and put those into table 4.
Table 1
id FirstName LastName
-------------------------
1 mr.xxxx xxx
2 mr.ssss sss
3 mr.yyyy yyy
Table 2
order_id deliver_date id tracking_number
----------------------------------------------
01 10/01/2017 1 1
02 10/01/2017 2 2
03 10/01/2017 3 3
Table 3
order_id total_price item qty
-----------------------------------------------
01 some price xx some quantity xx
02 some price xx some quantity xx
03 some price xx some quantity xx
Table 4
FirstName, LastName, deliver_date, order_id, total_price
I try to do it like this:
INSERT INTO RECEIPT (CUST_FNAME, CUST_LNAME, CUST_EMAIL, CUST_MOBILE, CUST_ADDRESS, CUST_CITY, CUST_STATE, CUST_POSTCODE, DELIVERY_DATE, TOTAL_PRICE, CUST_ID, ORDER_ID)
VALUES (SELECT CUSTOMER.CUST_FNAME, CUSTOMER.CUST_LNAME, CUSTOMER.CUST_EMAIL, CUSTOMER.CUST_MOBILE, CUSTOMER.CUST_ADDRESS, CUSTOMER.CUST_CITY, CUSTOMER.CUST_STATE, CUSTOMER.CUST_POSTCODE , ORDERS.DELIVERY_DATE, "ORDER DETAIL".TOTAL_PRICE, ORDERS.CUST_ID, ORDERS.ORDER_ID FROM CUSTOMER, ORDERS, "ORDER DETAIL" WHERE CUSTOMER.CUST_ID = ORDERS.CUST_ID AND ORDERS.ORDER_ID = "ORDER DETAIL".ORDER_ID)
But I get an error :
SQL0412N Multiple columns are returned from a subquery that is allowed only one column. SQLSTATE=42823
When using INSERT statement while selecting data from another table, you need to omit VALUES keyword.
So, it should be
INSERT INTO <TABLE_NAME>(col1, col2...)
SELECT col1, col2...
Also, make sure have same number of columns with same in same sequence, otherwise, you will be inserting wrong values or your query will throw error due to mis-match data type.
try this:
insert into table4 (FirstName, LastName, deliver_date, order_id, total_price)
select f1.FirstName, f1.LastName, f2.deliver_date, f2.order_id, f3.total_price
from table1 f1
inner join table2 f2 on f1.id=f2.id
inner join table3 f3 on f2.order_id=f3.order_id
You have the error in " ...VALUES (SELECT CUSTOMER.CUST_FNAME, ... " in the first column to insert, maybe this sub-query has more than 1 row.
You must adjust this query to return 1 row only (more filters).
Anyway other form to backup your values to another new table, is selecting the exactly columns from your new table and save this query into a .csv file.
Example:
CREATE TABLE new_table
(
id SERIAL NOT NULL,
FirstName VARCHAR,
LastName VARCHAR
....
);
SELECT table1.FirstName, table2.LastName, ...
FROM table1
INNER JOIN ....
-- this query you must save into a csv file (if your DB engine is allowed to save to csv).
After you have the file ready, you must load again in the new table.

One SQL statement for counting the records in the master table based on matching records in the detail table?

I have the following master table called Master and sample data
ID---------------Date
1 2014-09-07
2 2014-09-07
3 2014-09-08
The following details table called Details
masterId-------------Name
1 John Walsh
1 John Jones
2 John Carney
1 Peter Lewis
3 John Wilson
Now I want to find out the count of Master records (grouped on the Date column) whose corresponding details record with Name having the value "John".
I cannot figure how to write a single SQL statement for this job.
**Please note that join is needed in order to find master records for count. However, such join creates duplicate master records for count. I need to remove such duplicate records from being counted when grouping on the Date column in the Master table.
The correct results should be:
count: grouped on Date column
2 2014-09-07
1 2014-09-08
**
Thanks and regards!
This answer assumes the following
The Name field is always FirstName LastName
You are looking once and only once for the John firstname. The search criteria would be different, pending what you need
SELECT Date, Count(*)
FROM tblmaster
INNER JOIN tbldetails ON tblmaster.ID=tbldetails.masterId
WHERE NAME LIKE 'John%'
GROUP BY Date, tbldetails.masterId
What we're doing here is using a wilcard character in our string search to say "Look for John where any characters of any length follows".
Also, here is a way to create table variables based on what we're working with
DECLARE #tblmaster as table(
ID int,
[date] datetime
)
DECLARE #tbldetails as table(
masterID int,
name varchar(50)
)
INSERT INTO #tblmaster (ID,[date])
VALUES
(1,'2014-09-07'),(2,'2014-09-07'),(3,'2014-09-08')
INSERT INTO #tbldetails(masterID, name) VALUES
(1,'John Walsh'),
(1,'John Jones'),
(2,'John Carney'),
(1,'Peter Lewis'),
(3,'John Wilson')
Based on all comments below, this SQL statement in it's clunky glory should do the trick.
SELECT date,count(t1.ID) FROM #tblmaster mainTable INNER JOIN
(
SELECT ID, COUNT(*) as countOfAll
FROM #tblmaster t1
INNER JOIN #tbldetails t2 ON t1.ID=t2.masterId
WHERE NAME LIKE 'John%'
GROUP BY id)
as t1 on t1.ID = mainTable.id
GROUP BY mainTable.date
Is this what you want?
select date, count(distinct m.id)
from master m join
details d
on d.masterid = m.id
where name like '%John%'
group by date;