tricky subtraction on the same column - sql

I have a table named "prices" with 3 fields, one for country, one for the price and one for the date.
I need to make a difference between the price of each country in determined date.
i was making this code, and it works, but is making a substraction of each value on the first column, against each value on the other.
SELECT c1.value1-c2.value2 AS DIFERENCIAL
FROM (
SELECT PRICE AS value1
FROM PRICES_TABLE WHERE P = 'GERMANY'
AND (FECHA BETWEEN '17/01/2016' AND '17/01/2016')
) AS c1,
(
SELECT PRICES AS value2
FROM PRICES_TABLE WHERE P = 'PANAMA'
AND (FECHA BETWEEN '17/01/2016' AND '17/01/2016')
) AS c2
Is not what i want, if i have the values of lets say 23 values for today, and its country have assigned 23 values, i want vale1, value2.... value23 of the first column to be subtracred with value1...value23 on the second column.
Instead, is making c1.value1-c2.value1, c1.vale1-c2.value2... c1.value1-c2.value23, c1.value2-c2.value, c1,value2-c2.value2... c1.value2-c2.value23 etc.
Any idea?

If I understand correctly, you can use conditional aggregation or a join approach. So, this is one method:
SELECT ptg.fecha, ptg.hours, (ptg.prices - ptp.prices) AS DIFERENCIAL
FROM (SELECT pt.*
FROM PRICES_TABLE pt
WHERE P = 'GERMANY' AND FECHA = '2016-01-17'
) ptg JOIN
(SELECT pt.*
FROM PRICES_TABLE pt
WHERE P = 'PANAMA' AND FECHA = '2016-01-17'
) ptp
ON ptg.fecha = ptp.fecha and ptg.hours = ptp.hours;

Related

Getting value from MAX(Date) Row in SQL Server

I am trying to get the last supplier of an item, by using the MAX function. What I am trying to achieve is showing what the supplier name was for the row with the MAX(Date) for all the stock items (shown below as account links).
The code I am using bring up multiple dates for the same accountlink, and I am struggling to see why. My code is:
SELECT
MAX(TxDate) AS Date,
ST.AccountLink,
V.Account AS Supplier
FROM _bvSTTransactionsFull AS ST
JOIN Vendor V on ST.DrCrAccount = V.DCLink
WHERE Module = 'AP'
AND Id = 'OGrv'
GROUP BY ST.AccountLink, V.Account
ORDER BY AccountLink
But my results look like the below
Try this out
select AccountLink,Supplier,date from(SELECT
ST.AccountLink,
V.Account AS Supplier,
TxDate as [date],
row_number()over(partition by ST.AccountLink order by TxDate desc)rownum
FROM _bvSTTransactionsFull AS ST
JOIN Vendor V on ST.DrCrAccount = V.DCLink
WHERE Module = 'AP'
AND Id = 'OGrv')t
where t.rownum = 1
The group by has been removed and ranking function is used to achieve the output
You need a simple subquery to select the last supplier.
select X.supplier as LastSupplier, X.Date as lastDate, X.AccountLink
from _bvSTTransactionsFull X
where X.Date = (select max(date)
from _bvSTTransactionsFull Y
where Y.AccountLink=X.AccountLink)
The subquery extracts the last date for any accountLink, so you can use it on the outer where condition.

How to join table is sql?

I have two tables which name shoes_type and shoes_list. The shoes_type table includes shoes_id, shoes_size, shoes_type, date, project_id. Meanwhile, on the shoes_list table, I have shoes_quantity, shoes_id, shoes_color, date, project_id.
I need to get the sum of shoes_quantity based on the shoes_type, shoes_size, date, and also project_id.
I get how to sum the shoes_quantity based on color by doing:
select shoes_color, sum(shoes_quantity)
from shoes_list group by shoes_color
Basically what I want to see is the total quantity of shoes based on the type, size, date and project_id. The type and size information are available on shoes_type table, while the quantity is coming from the shoes_list table. I expect to see something like:
shoes_type shoes_size total quantity date project_id
heels 5 3 19/10/02 1
sneakers 5 3 19/10/02 1
sneakers 6 1 19/10/05 1
heels 7 5 19/10/03 1
While for the desired result, I have tried:
select shoes_type, shoes_size, date, project_id, sum(shoes_quantity)
from shoes_type st
join shoes_list sl
on st.project_id = sl.project_id
and st.shoes_id = sl.shoes_id
and st.date = sl.date
group by shoes_type, shoes_size, date, project_id
Unfortunately, I got an error that says that the column reference "date" is ambiguous.
How should I fix this?
Thank you.
The date column exists in both tables, so you have to specify where to select it from. Replace date with shoes_type.date or shoes_list.date
Qualify all column references to remove the "ambiguous" column error:
select st.shoes_type, st.shoes_size, st.date, st.project_id, sum(slshoes_quantity)
from shoes_type st join
shoes_list sl
on st.project_id = sl.project_id and
st.shoes_id = sl.shoes_id and
st.date = sl.date
group by st.shoes_type, st.shoes_size, st.date, st.project_id;
If you want all columns from shoes_type, you might find that a correlated subquery is faster:
select st.*,
(select sum(slshoes_quantity)
from shoes_list sl
where st.project_id = sl.project_id and
st.shoes_id = sl.shoes_id and
st.date = sl.date
)
from shoes_type st;

SQL: How to filter by column with a Union

I'm very new to SQl so I'm not sure how to frame my question for a google search.. Basically, I'm trying to UNION two sets of columns. They have very similar information; Set A is a series of products with a column for the vendor. Set B is a series of products without a vendor.
What I want to do is filter set A such that only a certain vendor's products are show (Which is what I did with a WHERE clause). But then, I want to union Set A and Set B such that the values in Set B will will only display (and combine) where there is an entry in Set A for the product.
That is, to explain better, I want Set B to 'look at' Set A. It will see that Set A only has items from a certain vendor and Set B will then remove items that Set A does not have (items that are NOT from that vendor).
Any thoughts? Thank you,
Code below:
SELECT ([Transfer_From]
,'Transfer_To' = [WAREHOUSE_CODE]
,'Product_Number' = [PRODUCT_NUMBER]
,'QTY_Trans' = [quantity_received]
,'Transfer_Date' = [received_date]
FROM [fstrkdb_1].[dbo].[Inventry]
WHERE vendor_number = '1074'
UNION
SELECT [Transfer_From]
,[Transfer_To]
,[Product_Number]
,'QTY_Trans' =[Quantity_Allocated]
,[Transfer_Date]
FROM [fstrkdb_1].[dbo].[InvtransFromWhs]
ORDER BY Transfer_Date
GO
One way is to use EXISTS in the WHERE clause. A CTE helps avoid repeating the first query:
WITH a as (
SELECT Transfer_From, WAREHOUSE_CODE as Transfer_To, Product_Number,
quantity_received as QTY_Trans, received_date as Transfer_Date
FROM [fstrkdb_1].[dbo].[Inventry]
WHERE vendor_number = '1074'
)
SELECT a.*
FROM a
UNION ALL
SELECT Transfer_From, Transfer_To, Product_Number, Quantity_Allocated
Transfer_Date
FROM [fstrkdb_1].[dbo].InvtransFromWhs ifw
WHERE EXISTS (SELECT 1 FROM a WHERE a.Product_Number = ifw.Product_Number)
ORDER BY Transfer_Date;
You only need UNION if you are expecting duplicates. The queries should not be creating unexpected duplicates.
WITH DataSet1 as (
SELECT ([Transfer_From]
,'Transfer_To' = [WAREHOUSE_CODE]
,'Product_Number' = [PRODUCT_NUMBER]
,'QTY_Trans' = [quantity_received]
,'Transfer_Date' = [received_date]
FROM [fstrkdb_1].[dbo].[Inventry]
WHERE vendor_number = '1074'),
DataSet2 as (
SELECT [Transfer_From]
,[Transfer_To]
,[Product_Number]
,'QTY_Trans' =[Quantity_Allocated]
,[Transfer_Date]
FROM [fstrkdb_1].[dbo].[InvtransFromWhs] A
INNER JOIN dataset1 B
on A.Product_number = B.Product_number)
SELECT * FROM dataset1
UNION
SELECT * FROM dataset2
ORDER BY Transfer_Date
What this would do is generate dataset1. then use the products from dataset1 as a filter on dataset2 and then union those two sets together.

Writing a query for multiple fields using IN

SELECT a.First_Name,b.EMPID,c.Phn
FROM NAME a,Emp b,Phone c
WHERE b.Emptype = 'New'
AND a.First_name,b.Last_name,C.Phn = (SELECT a.First_Name,b.Last_name,c.Phn
FROM NAME a,Emp b,Phone c
WHERE b.Emptype = 'Old')
Basically, I want to search for new customers which have the same details (First name, Last name and Phone) as the old customers. An old customer can be converted into a new customer but its details are retained. Hence, the only thing that changes is the emptype.
Eg. (John McEnroe 47589876 Old) when converted becomes (John McEnroe 475898876 New)
[First_name,Last_name,Phone,Emptype]
Dude, here's a query that uses EXISTS.
The main difference between Exists and IN is that Exists queries using INDEX but IN goes like a lot of OR toghether.
SELECT a.First_Name
,b.EMPID
,c.Phn
FROM NAME a
,Emp b
,Phone c
WHERE b.Emptype = 'New'
AND EXISTS (Select TOP 1 1 FROM
NAME x
,Emp y
,Phone z
WHERE
x.First_Name = a.First_Name
AND y.Last_name = b.Last_name
AND z.Phn = c.Phn
AND y.Emptype = 'Old'
)
Now, looking at your query, you have 3 tables, not joined toghether (Name, Emp, Phone) so you have a real mess with the data that will come as an output. Will be, basically this formula:
(1st Table rows qty) Multiplied by (2nd Table rows qty) Multiplied by (3rd Table rows qty)
Means that if each table have 100 rows, you'll get this:
100 x 100 x 100 = 1000000 Rows in the result (Awful right?)
WITH tempTable as (
SELECT a.First_Name,b.EMPID,c.Phn
FROM NAME a,Emp b,Phone c
where b.Emptype = 'Old'
)
select a.First_Name,b.EMPID,c.Phn
FROM NAME a,Emp b,Phone c,tempTable t
where b.Emptype = 'Old' and a.First_Name = t.First_Name
AND b.Last_name = t.Last_name
AND c.Phn = t.Phn;
try this... or use subquery...
You can use multiple columns for an IN query:
AND (a.First_name,b.Last_name,C.Phn) IN (SELECT a.First_Name,b.Last_name,c.Phn
FROM ... )

Replace or updates null values with the sum of amount spend for customers

At first, I have a table looks like as below:
cust_id/Bill_amt/Brand/BrandA/BrandB/Total_value
100/350/A/NULL /NULL/NULL
100/250/A/NULL/NULL/NULL
100/100/B/NULL /NULL/NULL
300/200/B/NULL /NULL/NULL
I would like to replace the 'null' values with the amount of spend for the same customer, as you can see from the above table, there is repeated customers with cust_id 100, this is because this customer purchase both brand A and B at different dates, thus, I need your help to sum up everything for that customer in one row, after putting everything in one row, you will notice that there is 3 rows with the same record (duplication), which is shown as below:
cust_id/Bill_amt/Brand/BrandA/BrandB/Total_value
100/350/A/600/100/700
100/250/A/600/100/700
100/100/B/600/100/700
300/200/B/0/200/200
For example,cust_id 100 spend $600(350+250) for brand A, and this customer only spend $100 (look at the 3rd row of cutsomer_id 100) for brand B, thus, the total value is $700 (600+100).
I hope this explanation is clear enough for you.
After update the table as shown below, we will remove the duplicates by ourselves.
Please kindly provide us the SQL query to help us to replace or update the 'null' values with the sum of bill_amt as we have 200000 plus record to do it.
Thank you very much for taking your time to reply us.
why do you need BrandA,BrandB,Total_value column ?that is not require.
;WITH cte
AS (SELECT cust_id,
brand,
Sum(bill_amt) bill_amt
FROM #t
GROUP BY rollup( cust_id, brand ))
UPDATE #t
SET branda = COALESCE(a.bill_amt, 0),
brandb = COALESCE(c.bill_amt, 0),
total_value = COALESCE(d.bill_amt, 0)
FROM #t b
LEFT JOIN cte a
ON a.cust_id = b.cust_id
AND a.brand = 'A'
LEFT JOIN cte c
ON b.cust_id = c.cust_id
AND c.brand = 'B'
LEFT JOIN cte d
ON b.cust_id = d.cust_id
AND d.brand IS NULL
SELECT *
FROM #t