Joining 3 tables & inserting in a 4th table in SQL server - sql

I am joining 3 tables - items , sales , & purchase.
And then, inserting the combined data into a 4th table FULL_DETAIL_OF_ITEMS.
ITEMS table has columns : ITEM_CD, ITEM_NM, COM_CD, SALE_RT, PURCH_RT, MRP
SALES table has columns : ITEM_CD, ITEM_NM, SALE_QTY
PURCHASE table has columns : ITEM_CD, ITEM_NM, PURCH_QTY
FULL_DETAIL_OF_ITEMS table has columns :
ITEM_CD, ITEM_NM, COM_CD, SALE_RT, PURCH_RT, MRP, SALE_QTY, PURCH_QTY
The query is:
insert into FULL_DETAIL_OF_ITEMS
SELECT
Items.Item_CD,
Items.Item_NM ,
ITEMS.COM_CD,
ITEMS.SALE_RT,
ITEMS.PURCH_RT,
ITEMS.MRP,
SALES.SALE_QTY,
PURCHASE.PURCH_QTY
FROM items
JOIN sales on ITEMS.ITEM_CD = sales.ITEM_CD
JOIN purchase on items.ITEM_CD = purchase.ITEM_CD
Items table is filled but sales & purchase tables are empty, so on executing the above query nothing happens? Why so?
At least it should insert rest of the columns from the items table into the 4th table.
It finds that in sales table - sale_qty , & in purchase table, purch_qty is empty, so it should fill null in these columns in the final table & fill rest of the columns as they are picked from item table which consists data so it should fill that.
But its not doing so?
According to the definition of JOIN, ITEM_CD in item table is not matching with the ITEM_CD column of the sales & purchase table as it is empty in both, so this is the reason.
But I want that rest of the data is inserted in the 4th table, then is there any way to do this?

You need to change those join statements to left join.
By default, a join is an "inner join", which means that only rows that exist on both sides of the join will be included. A "left join" includes all rows on the "left" side of the join.
Example:
from items
left join sales on ITEMS.ITEM_CD =sales.ITEM_CD
left join purchase on items.ITEM_CD =purchase.ITEM_CD

You can minimize your query using a select into statement which will, by default, creates a new table at run time.
select Items.Item_CD,Items.Item_NM,Items.COM_CD,Items.Mrp,Items.Purchase_RT,Items.Sale_RT,
purchase.Purchase_QTY,Sales.Sale_QTY
into full_details_of_items
from Items
inner join purchase
inner join Sales
on purchase.Item_CD=Sales.Item_CD
on items.Item_CD=purchase.Item_CD

Related

SQL Join Table A Column A to Table B Column A or B

I have 2 tables - A Spend Table and a Sales Table
Spend Table Schema:
Spend_ID,
Spend_amount
Sales Table Schema:
Sales_ID_A,
Sales_ID_B,
Sales_amount
I want to do a left join of the spend table to the sales table. The join key from the spend table is the Spend_ID and i want to join when it matches the value in either Sales_ID_A or Sales_ID_B i.e. my match key on the sales table is in 2 columns. So in a way its like applying an 'or' condition to the join on the sales table Sales_ID_A or Sales_ID_B. If a match is found in Sales_ID_A, then no need to check Sales_ID_B. Only check Sales_ID_B if no match is found in Sales_ID_A. How do i achieve this with SQL?
Sample Data Illustration:
See screenshot
The columns called sales_id_a and sales_id_b are actually spend IDs and should better be called spend_id_a and spend_id_b.
You want to join on the first ID, but if that is null, you want to join on the second ID. Use COALESCE for this:
select *
from sales
left join spend on spend.spend_id = coalesce(sales.sales_id_a, sales.sales_id_b)

Left Join misbehaving - VBA SQL

Table 1: Customer Info Data (has ~50K records)
Table 2: Sales by customer ID (has ~25K records)
When I am performing a left join of Sales data from Table 2 on Table 1 based on the Customer ID, the output has a handful of records (~500) with a unit increase in the sales quantity. For e.g. sales quantity for customer #1 is 200, the sale quantity that I am getting in my joined output is 201. Note again that this is only for handful of records, for the majority of the data, it is joined absolutely correctly.
The SQL query is a pretty standard one:
SELECT [Table1$].[ID], Name, Volume, Amount
FROM [Table1$] LEFT JOIN [Table2$] ON [Table1$].[ID] = [Table2$].[ID]
What is weird is that this error is only for a few records and it is changing only by a unit for all of them. What do you think could be the potential reason here? Note that I run this SQL query from VBA.
Edit:
Maybe if I add an image, it would help, I have masked my data:
Table1, blue colored column is the joined column, I have filtered for the ID where there is a problem:
Table2, source of the joined column, as you can see it is 20, but the value that has been joined with table 1 is 21. Interestingly, there is no ID with value 21 in table2
There is certainly a space or something that makes seemingly identical IDs different. To make sure do a select distinct id on the sales table.

Outputting the data from several sql tables without having a common value

I have a select query which combined several tables. PRODUCTION_ORDER_RESULTS, PRODUCTION_ORDERS and SERVICE_GUARANTY_NEW have common value however STOCKS table does not.
SELECT PR_ORDERS.ARRIVED_CITY,
PR_ORDERS.MONTAJ_DATE,
PR_ORDER_RESULT.TRANSFER_DATE,
PR_ORDERS.P_ORDER_ID,
PR_ORDER_RESULT.P_ORDER_ID,
SG.SALE_CONSUMER_ID,
SG.IS_SERI_SONU,
S.BRAND_ID,
S.PROPERTY
FROM workcube_test_1.PRODUCTION_ORDER_RESULTS PR_ORDER_RESULT,
workcube_test_1.PRODUCTION_ORDERS PR_ORDERS,
workcube_test_1.SERVICE_GUARANTY_NEW SG,
workcube_test_1.STOCKS S
WHERE PR_ORDER_RESULT.P_ORDER_ID = PR_ORDERS.P_ORDER_ID
AND PR_ORDER_RESULT.PR_ORDER_ID = SG.PROCESS_ID
when I run the query, it shows the output as below.
The problem here is there are four data rows returned from PRODUCTION_ORDER_RESULTS, PRODUCTION_ORDERS, SERVICE_GUARANTY_NEW and once I have added the STOCKS table, arrived_city, montaj_date, transfer_date columns are side by side with STOCKS table's rows, but the columns value should be null, not filled with data.
The way I tried is UNION of STOCKS table, however unioned table values are ignored, can not use them in html blocks.
there needs to be at least one more join condition among tables where there's for STOCKS table, I think there might exist such a column STOCK_ID within a table such as PRODUCTION_ORDER_RESULTS in order to join with STOCKS table. I think this should be the reason for multiple returning rows. If there's no common column, then the returning data will be produced as many as the number of records within STOCK table due to existing CROSS JOIN logic within the current query. So rearrange your query as
SELECT PR_ORDERS.ARRIVED_CITY,
PR_ORDERS.MONTAJ_DATE,
PR_ORDER_RESULT.TRANSFER_DATE,
PR_ORDERS.P_ORDER_ID,
PR_ORDER_RESULT.P_ORDER_ID,
SG.SALE_CONSUMER_ID,
SG.IS_SERI_SONU,
S.BRAND_ID,
S.PROPERTY
FROM workcube_test_1.PRODUCTION_ORDER_RESULTS PR_ORDER_RESULT
JOIN workcube_test_1.PRODUCTION_ORDERS PR_ORDERS
ON PR_ORDER_RESULT.P_ORDER_ID = PR_ORDERS.P_ORDER_ID
JOIN workcube_test_1.SERVICE_GUARANTY_NEW SG
ON PR_ORDER_RESULT.PR_ORDER_ID = SG.PROCESS_ID
JOIN workcube_test_1.STOCKS S
ON PR_ORDER_RESULT.STOCK_ID = S.ID

Why do repeated values appear in SQL results

I'm with a doubt about joins. For example, using an example database dvdrental, this query:
SELECT customer.customer_id
, first_name
, last_name
FROM customer
INNER JOIN payment ON Customer.customer_id = Payment.customer_id
Some records appear repeated, for example, it appears 3 times "342 Harold Martino" like:
342 Harold Martino
342 Harold Martino
342 Harold Martino
Do you know why it appears repeated records like in this example that appears the same Record 3 times? This repetition means that there are 3 records in the payment table where customer_id = 342? But this query "select * from payment where customer_id = 342" returns 32 records. So I'm not understanding properly how the join works.
There are many resources around this, so to be short your expression says this in plain english:
Get all the records from the customer table
Then for each of those records, get every payment record that has the same value in the customer_Id field.
return a single row for each payment record that duplicates all the fields from the customer record for each row in the payment record.
Finally, only return 3 columns:
the customer_id column from the customer table
the first_name column that is in one of the customer or payment table
the last_name column that is in one of the customer or payment table
Note that we didn't bring back any columns from the payment table... (I assume first_name and last_name are fields in the customer table...)
Keep in mind, a CROSS JOIN (or a FULL OUTER JOIN) is a join that says take all fields from the left side and create a single row combination that is multiplied by the right side, so for every row on the left, return a combination of the left row with every row on the right. So the number of rows returned in a CROSS JOIN is the number of rows in the current table, multiplied by the number of rows in the joined table.
In your query, an INNER JOIN or LEFT INNER JOIN will produce a recordset that includes all the fields from the current table structure and will include fields from the joined table as well.
the implicit LEFT component specifies that only records that match the existing table structure should be returned, so in this case only Payment records that match a customer_id in the currently not filtered customer table will be returned.
The number of resulting rows is the number of rows in the joined table that have a match in the current table.
If instead you want to query:
Select all the customers that have payments
then you can use a join, but you should also use a DISTINCT clause, to only return the unique records:
SELECT DISTINCT customer.customer_id
, first_name
, last_name
FROM customer
INNER JOIN payment ON Customer.customer_id = Payment.customer_id
An alternative way to do this is to use a sub-query instead of a join:
SELECT customer_id
, first_name
, last_name
FROM customer
WHERE EXISTS (SELECT customer_id FROM payment WHERE payment.customer_id = customer.customer_id)
The rules on when to use one style of query over the other are pretty convoluted and very dependant on the number of rows in each table, the types of indexes that are available and even the type or version of the RDBMS you are operating within.
To optimise, run both queries, compare the results and timing and use the one that fits your database better. If later performance becomes an issue, try the other one :)
Select the Customer_id field

Updating table and setting the field values to the result of a left join

I have a table Sales with the field Vendor ("Company A", "Company B", "Trader X"), and I have made a separate table called Vendors with two fields: VendorID and VendorName.
I want to delete the Vendor field in the table Sales and replace it with a VendorID field and fill the fill the field with the corresponding VendorIDs. In other words replace the names of the vendors in the Sales table with their ID from the Vendors table.
I have tried numerous solutions but they do not work. Here is one that I think will work. Some entries in the Sales table do not have any Vendors listed. There are 203 entries and the left join, when run on its own, returns all 203 vendors and the appropriate null values.
Update Sales
Set Sales.VendorID = (Select VendorID From Vendors v Left Join Sales s on
v.VendorName = s.Vendor);
When I run this I get a dialog box asking :
Enter Parameter Value
Or I get the error message :
Operation must use an updateable query
I am using MS Access 2016.
I think that you don't need a subquery, you could just use the UPDATE ... JOIN ... SET syntax, like :
UPDATE sales AS s
INNER JOIN Vendors AS v ON v.VendorName = s.Vendor
SET s.VendorID = v.VendorID