Need help on writing sql select statement - sql

I have a question about selecting rows from a table.
For example I have a table which includes information about stock movements. I wish to select the product code, latest date, latest price of each product in the table.
Stock movements table
Stock Movement Code Product code Date Price
1 1 15.06.2015 9$
2 2 17.06.2015 10$
3 2 18.06.2015 8$
4 1 19.06.2015 7$
5 3 20.06.2015 11$
6 2 21.06.2015 12$
7 3 22.06.2015 13$
I wish to select the latest date,latest price of each product from above table.
For this example I am waiting a result like below.
Stock Movement Code Product code Date Price
4 1 19.06.2015 7$
6 2 21.06.2015 12$
7 3 22.06.2015 13$
Could you please help me to write the SQL of this select statement?

Try this:
SELECT sm.*
FROM stock_movement sm
WHERE NOT EXISTS(
SELECT 'NEXT'
FROM stock_movement sm2
WHERE sm2.[Product code] = sm.[Product code]
AND sm2.date > sm.date
)

Related

Multiple select statements - Single result

I have a product list view and a v1 value which is used for mapping
For example in erp view it look like below
PRODUCT_ID
PRODUCT_NAME
QUANTITY
v1
1
WOOD PALLET 120x80
10
25
2
WOOD PALLET 200x80
5
25
25
RAW MATERIAL WOOD
100
25
in postgres we have for it 2 tables
Table: PRODUCTS
PRODUCT_ID
PRODUCT_NAME
QUANTITY
1
WOOD PALLET 120x80
10
2
WOOD PALLET 200x80
5
25
RAW MATERIAL WOOD
100
Table: PRODUCTS_MAPPING
PRODUCT_ID
MAPPING_KEY
1
25
2
25
25
25
Now I need a query that will give only one row result which is total of quantity grouped by v1 so result should be 115
I try below query
(
SELECT
SUM( pr.quantity )
FROM
products AS pr
WHERE
pr.product_id = ( SELECT map.product_id FROM products_mapping AS map WHERE mapping_key = v1 )
)
My problem is that after WHERE there is second SELECT statement which is giving multiple results. I need a statement which will do below calculation:
Check v1 value (25)
Go to product mapping table. Find 3 entry for mapping key 25.
Go to Product table and sum quantity for products_id 1,2,3 and give result 10+5+100 = 115
If I understood properly you only want a single result but you haven't put a group by clause in your sentence.
SELECT sum(pr.quantity) FROM products pr JOIN products_mapping map
on pr.product_id=map.product_id WHERE
mapping_key=v1 group by map.mapping_key
I have rewritten your statement using joins.

SQL: Getting Duplicate Data When Attempting to Sum and Join 2 Tables

In Essence, I have two tables (purchases and sales) that I need to join together. Both tables have different Primary Keys, but they share the same foreign key. Every time a purchase is made, a new entry is made (with it's own primary key). Every time a sale is made, a new entry is made (with its own key).
Summary of Used Tables:
Purchase Data
Individual Product Cost (AS IPC)
Sales Tax (AS ST)
Quantity (AS Q)
SKU (Foreign Key)
Primary Key (AS PK)
Sales
Amount Sold (AS AS)
Total (AS T)
SSKU(Foreign Key)
Primary Key (AS PK)
When I attempt to Sum and Join the data based on the product I get weird results.
Purchase Table Data:
SKU | IPC | ST | Q | PK
1 2.40 .02 5 1
2 5.00 .05 20 2
3 4.00 .04 5 3
1 5.00 .04 20 4
Sales Table:
SSKU | T | AS | PK
1 10 2 1
2 9 1 2
3 9 4 3
1 9 1 4
2 9 2 5
1 9 2 6
1 9 4 7
Expected Results
SKU | (IPC + ST)Q | Q | SUM AS | SUM T
1 354.9 25 9 37
2 101 20 3 9
3 80.8 5 4 18
When trying the script creator in OpenOffice Base, It would give me the expected results for product 3, but it would be wrong for products 1 and 2.
I read up on SQL programming, and attempted my hand at it. I THINK this would solve the issue by summing the two tables separately before merging. Instead, I keep receiving an error now, and I can't find the mistake.
Current Code:
SELECT
"A"."SKU"
,SUM(( "A"."Individual Product Cost" + "A"."Sales Tax" ) * "A"."Quantity")
,"A"."Quantity"
,"D"."Sales"
,"D"."Sold"
FROM "PurchaseData" AS "A"
Inner Join
(
Select
"ACT"."SSKU"
,SUM("ACT"."Amount Sold") AS Sold
,SUM("ACT"."Total") AS Sales
From
"Sales" AS ACT
GROUP BY
"ACT"."SSKU"
)
AS D
on "A"."SKU" = "D"."SSKU"
Group By
"A"."SKU"
EDIT:
According to a random online Syntax checker, it's line 3 (I don't see it).
According to Openoffice Base:
SQL Status: HY000
Error code: 1000
syntax error, unexpected $end, expecting BETWEEN or IN or SQL_TOKEN_LIKE
Thanks to Jayvee, I got it working!
Select
"A"."SKU"
,"B"."Sold"
,"B"."Sales"
,"A"."Total Cost"
,"A"."Total Purchased"
From
-- First Sub Query --
(
Select
"PD"."SKU" As SKU
,SUM(( "PD"."Individual Product Cost" + "PD"."Sales Tax" ) *"PD"."Quantity") AS "Total Cost"
,SUM ("PD"."Quantity") AS "Total Purchased"
From
"PurchaseData" AS PD
GROUP BY
"PD"."SKU"
)
As A
--End First--
Join
--Start 2nd--
(
Select
"ACT"."SSKU" AS ASKU
,SUM("ACT"."Amount Sold") AS Sold
,SUM("ACT"."Total") AS Sales
From
"Sales" As ACT
GROUP BY
"ACT"."SSKU"
)
As B
--End 2nd--
On
"B"."ASKU" = "A"."SKU"
you can sum purchase data in a subquery, the same as you did with sales, and then join both subqueries without aggregation:
Select
"A"."SKU"
,"B"."Sold"
,"B"."Sales"
,"A"."Total Cost"
,"A"."Total Purchased"
From
-- First Sub Query --
(
Select
"PD"."SKU" As SKU
,SUM(( "PD"."Individual Product Cost" + "PD"."Sales Tax" ) *"PD"."Quantity") AS "Total Cost"
,SUM ("PD"."Quantity") AS "Total Purchased"
From
"PurchaseData" AS PD
GROUP BY
"PD"."SKU"
)
As A
--End First--
Join
--Start 2nd--
(
Select
"ACT"."SSKU" AS ASKU
,SUM("ACT"."Amount Sold") AS Sold
,SUM("ACT"."Total") AS Sales
From
"Sales" As ACT
GROUP BY
"ACT"."SSKU"
)
As B
--End 2nd--
On
"B"."ASKU" = "A"."SKU"

Update rows based on rownumber in SQL Server 2012

Ive been given some data in a spreadsheet which will soon be going into an automated import so i cannot do any manual entry on the spreadsheet. The data basically has the following columns. Trayid, trayname, itemdescription and rownumber. I didnt build these tables myself or i would of built it differently but i have to stick to the format which is already set.
The Data that is being imported will look at followed.
Trayid | Trayname | ItemDescription | RowNumber
1 Tray 1 Product 1 1
Product 2 2
Product 3 3
Product 4 4
2 Tray 2 Product 1 1
Product 2 2
Product 3 3
Product 4 4
Product 5 5
What i need to do is update the trayid and trayname for each of the other rows following row 1, so for example it will look like.
Trayid | Trayname | ItemDescription | RowNumber
1 Tray 1 Product 1 1
1 Tray 1 Product 2 2
1 Tray 1 Product 3 3
1 Tray 1 Product 4 4
2 Tray 2 Product 1 1
2 Tray 2 Product 2 2
2 Tray 2 Product 3 3
2 Tray 2 Product 4 4
2 Tray 2 Product 5 5
Im guessing i need to use a curser or something but im not sure, i think it can be done by going down the rownumbers and stopping when it see's rownumber 1 again and then carrying on with the next trayid and trayname.
Sorry if what i need doesnt make sense, it was awkward to explain.
SQL tables have no inherent ordering. So you cannot depend on that. But, there is something that you can do:
Define an identity column in the source table.
Create a view on the source table that excludes the identity.
Bulk insert into the view.
This will assign a sequential number to rows in the same order as the original data. Let's call this id. Then you can do your update by doing:
with toupdate (
select t.*,
max(TrayId) over (partition by grp) as new_TrayId,
max(TrayName) over (partition by grp) as new_TrayName
from (select t.*,
count(TrayId) over (order by id) as grp
from t
) t
)
update toupdate
set TrayId = new_TrayId,
TrayName = new_TrayName
where TrayId is null;
The idea is to define groups of rows corresponding to each tray. The simple idea is to count the number of non-NULL values before any given row -- everything in a group will then have the same grp value. Window functions then spread the actual value through all rows in the group (using max()), and these values are used for the update.

Result set with multiplied rows into an SSRS report

I need to get this query into an SSRS report.
SELECT s.SR_Service_RecID -- will have 1 result
, p.Description -- will have 8 results
, t.notes -- will have 5 results
FROM SR_Service s
LEFT JOIN IV_Product p
ON p.SR_Service_RecID = s.SR_Service_RecID
LEFT JOIN Time_Entry t
ON t.SR_Service_RecID = s.SR_Service_RecID
This query is multiplying p.Description by t.Notes for the total number of rows as expected.
Result set:
SR_RecID Description Notes
12345 Product 1 Note 1
12345 Product 1 Note 2
12345 Product 1 Note 3
12345 Product 1 Note 4
12345 Product 1 Note 5
12345 Product 2 Note 1
12345 Product 2 Note 2
12345 Product 2 Note 3
12345 Product 2 Note 4
12345 Product 2 Note 5
Etc..
How can this be put into an SSRS report so it displays only the actual results, not the multiplied amounts?
SR_RecID
12345
Description
Product 1
Product 2
Product 3
Product 4
Product 5
Product 6
Product 7
Product 8
Notes 1
Notes 2
Notes 3
Notes 4
Notes 5
Do I need to rework the query or can this be done on the SSRS end of things?
Yes, you can achieve this by adding tablix:
and using 3 adjacent groups (grouped by each field) like follows:
You will get this result:

Rows being multiplied by number of results

SELECT s.SR_Service_RecID -- will have 1 result
, p.Description -- will have 8 results
, t.notes -- will have 5 results
FROM SR_Service s
LEFT JOIN IV_Product p
ON p.SR_Service_RecID = s.SR_Service_RecID
LEFT JOIN Time_Entry t
ON t.SR_Service_RecID = s.SR_Service_RecID
This query is multiplying p.Description by t.Notes for the total number of rows. Each p.Description is displaying 5 times against each individual t.notes.
Result set:
SR_RecID Description Notes
12345 Product 1 Note 1
12345 Product 1 Note 2
12345 Product 1 Note 3
12345 Product 1 Note 4
12345 Product 1 Note 5
12345 Product 2 Note 1
12345 Product 2 Note 2
12345 Product 2 Note 3
12345 Product 2 Note 4
12345 Product 2 Note 5
Etc..
I'm unsure how to resolve this one... any help would be appreciated.
[EDIT]:
As the results are correct how can you put this into an SSRS report to show only the correct amount of results as it will display all duplicated rows?
SR_RecID
12345
Description
Product 1
Product 2
Product 3
Product 4
Product 5
Product 6
Product 7
Product 8
Notes 1
Notes 2
Notes 3
Notes 4
Notes 5
If by "resolving" you mean how to only have 1 note for each SR_RecID and Description then you would need to select only 1 Notes for each by using Aggregate function (MAX, MIN, etc.).
Otherwise, as commented several times, your result is what to be expected.