Returning complex query on update sql - sql

I want to return query with multiple joins and with clause after updating something.
For example my query is:
WITH orders AS (
SELECT product_id, SUM(amount) AS orders
FROM orders_summary
GROUP BY product_id
)
SELECT p.id, p.name,
p.date_of_creation,
o.orders, s.id AS store_id,
s.name AS store_name
FROM products AS p
LEFT JOIN orders AS o
ON p.id = o.product_id
LEFT JOIN stores AS s
ON s.id = p.store_id
WHERE p.id = '1'
id
name
date
orders
store_id
store_name
1
pen
11/16/2022
10
1
jj
2
pencil
11/10/2022
30
2
ff
I want to return the exact query but with updated result in my update:
UPDATE products
SET name = 'ABC'
WHERE id = '1'
RETURNING up_qeury
Desired result on update:
id
name
date
orders
store_id
store_name
1
ABC
11/16/2022
10
1
jj

You can try UPDATE products ... RETURNING *. That may get you the content of the row you just updated.
As for UPDATE .... RETURNING someQuery, You Can't Do Thatâ„¢. You want to do both the update and a SELECT operation in one go. But that's not possible.
If you must be sure your SELECT works on the precisely the same data as you just UPDATEd, you can wrap your two queries in a BEGIN; / COMMIT; transaction. That prevents concurrent users from making changes between your UPDATE and SELECT.

Related

How can I perform this sql update using sql instead of using code?

I have been able to select this data, using these two sql queries
Query 1:
SELECT article_id, amount_required, amount_sold FROM products_articles,sales WHERE sales.product_id = products_articles.product_id
Query 2:
SELECT * FROM articles
What I want to do, is go through the first table (with amount sold and required) (it's fine that there are duplicate rows), and for each row in the table multiply the value of amount_sold and amount_required and then subtract that value from amount_in_stock where the ids match in the second table.
Example from the first row:
2 * 4 = 8, change amount_in_stock from 124 to 116.
And so on...
How can I do this using just sql?
UPDATE A
SET
A.amount_in_stock =(S.amountSold * S.amount_required)- A.amount_in_stock
FROM articles AS A
INNER JOIN
products_articles AS PA
ON PA.article_id= A.article_id
INNER JOIN Sales AS S
ON S.product_id=PA.product_id
Please try this:
Update articles a
inner join
(
SELECT article_id, sum(amount_required) amount_required, sum(amount_sold )amount_sold FROM products_articles inner join sales on sales.product_id = products_articles.product_id
group by article_id
)b on a.article_id=b.article_id
set a.amount_in_stock=a.amount_in_stock-(amount_required*amount_sold )
Since there could be multiple rows in product_articles and amount_sold I have used group by to sum the amounts.
For SQLite please try this:
Update articles
set amount_in_stock=(SELECT sum(amount_required) * sum(amount_sold ) FROM products_articles inner join sales on sales.product_id = products_articles.product_id
where products_articles.article_id=articles.article_id
group by article_id
)
where exists (SELECT * FROM products_articles inner join sales on sales.product_id = products_articles.product_id where products_articles.article_id=articles.article_id
)

SQL LEFT JOIN - Inner select not returning columns

I have two tables called 'Customers' and 'Orders'. Tables column names are as follow:
Customers: id, name, address
Orders: id, person_id, product, price
The desired outcome is to query all customers with one of their latest purchases. I have a lot of duplicates in 'Orders' table whereby two records with same time-stamp due to some bug.
I have written the following code but the issue is that the query does not return table 2(Orders) column values. Can anyone advise what the issue is?
SELECT C.Id,C.Name, O.item, O.price, O.product
FROM Customers C
LEFT JOIN
(
SELECT TOP 1 person_id
FROM Orders
WHERE status = 'Pending'
) O ON C.ID = O.person_id
Results: O.item, O.price, O.product values are all null
Edit: Sample Data
ID/ NAME/ ADDRESS/
1/ A/ Ad1/
2/ B/ Ad2/
3/ C/ Ad3/
ID/ Person ID/ PRODUCT PRICE/ Created Date
ID-1234/ 1/ Book/ $5/ 26-2-2017
ID-1235/ 1/ Book/ $5/ 26-2-2017
ID-1236/ 2/ Calendar/ $10/ 4-2-2017
ID-1238/ 1/ Pen/ $2/ 1-1-2016
Assuming that the id column in Orders is a primary key autoincrement, then the following should work:
SELECT c.id,
c.name,
COALESCE(t1.price, 0.0) AS price,
COALESCE(t1.product, 'NA') AS product
FROM Customers c
LEFT JOIN Orders t1
ON c.id = t1.person_id
LEFT JOIN
(
SELECT person_id, MAX(CAST(SUBSTRING(id, 4, LEN(id)) AS INT)) AS max_id
FROM Orders
GROUP BY person_id
) t2
ON t1.person_id = t2.person_id AND
t2.max_id = CAST(SUBSTRING(t1.id, 4, LEN(t1.id)) AS INT)
This answer assumes that taking the greatest order ID per customer will yield the most recent purchase. Ideally you should have a timestamp column which captures when a transaction took place. Note that even in the query above, we still have no way of knowing when the most recent transaction took place.
So where is the timestamp column? It's not mentioned in your table schema. But your description does not mention the status column either, and that is clearly in there.
Is orders.id unique? Is it the key for the Orders table?> If it is, then your schema has no way to identify "duplicate" records. You cannot mean to imply that only one order per customer is allowed, so if there are multiple orders for a single customer, how do we identify the duplicates? By the unmentioned timestamp column?
If there IS a `timestamp column, and that's how you would identify dupes, then use it.
SELECT C.Id,C.Name, O.item, O.price, O.product
FROM Customers C LEFT JOIN Orders o
on o.id = (Select Min(id) from orders
where person_id = c.Id
and timestamp = o.timestamp
and status = 'Pending')

SQL SUM, COUNT for only unique id

I want to calculate sum and count for only unique ids.
SELECT COUNT(orders.id), SUM(orders.total), SUM(orders.shipping) FROM "orders"
INNER JOIN "designer_orders" ON "designer_orders"."order_id" = "orders"."id"
WHERE (designer_orders.state = 'pending' OR
designer_orders.state = 'dispatched' OR
designer_orders.state = 'completed')
Do this only for unique orders ids.
Add orders.total only if orders.id is unique. Same goes for shipping.
Avoid adding duplicates.
For example, orders table inner joined designer_orders table:
OrderId Total Some designer order column
1 1000 2
1 1000 3
1 1000 5
2 100 7
3 133 8
4 1000 10
4 1000 20
In this case:
count of orders should be 4.
total of orders should be 2233.
Schema:
One order has many designer orders.
One designer order has only one order.
Try it this way
SELECT COUNT(o.id) no_of_orders,
SUM(o.total) total,
SUM(o.shipping) shipping
FROM orders o JOIN
(
SELECT DISTINCT order_id
FROM designer_orders
WHERE state IN('pending', 'dispatched', 'completed')
) d
ON o.id = d.order_id
Here is SQLFiddle demo
Since you are only interested whether any row with qualifying status exists in the table designer_orders, the most obvious query style would be an EXISTS semi-join. Typically fastest with potentially many duplicate rows in n-table:
SELECT COUNT(o.id) AS no_of_orders
,SUM(o.total) AS total
,SUM(o.shipping) AS shipping
FROM orders o
WHERE EXISTS (
SELECT 1
FROM designer_orders d
WHERE d.state = ANY('{pending, dispatched, completed}')
AND d.order_id = o.id
);
-> SQLfiddle demo
For fast SELECT queries with bigger tables (and at some cost for write performance), you would have a partial index like:
CREATE INDEX designer_orders_order_id_idx ON designer_orders (order_id)
WHERE state = ANY('{pending, dispatched, completed}');
The index condition must match the WHERE condition of the query to talk the query planner into actually using the index.
A partial index is particularly attractive if there are many rows with a status that does not qualify. Else, an index without condition might be the better choice overall.

MS SQL - Problem selecting a subset of records

I'm having a SQL brainfart moment. I am trying to get a set of records when any of the attribute IDs for that product is a certain value.
Problem is, I need to get all other attributes for that same product along with it.
Here's an illustration for what I mean:
Is there a way to do that? Currently I am doing this
select product_id
from mytable
where product_attribute_id = 154
But I obviously only get the single record:
Any help would be greatly appreciated. My SQL skills are a bit basic.
EDIT
There's one condition I forgot to mention. There are times where I need to be able to filter on two attribute IDs. For example, in the first image above, the lower set (product ID 31039) has attribute id 395. I would need to filter on 154, 395. The result would not include the top set (31046) which does not have an attribute id 395.
I think is what you're looking for:
SELECT * myTable where Product_Id IN (SELECT Product_Id FROM MyTable WHERE Product_AttributeID = #parameterValue)
In English: Get me all the records such that their product id is in the set of all product ids such that their attribute id is equal to #parameterValue.
EDIT:
SELECT * myTable where Product_Id IN (SELECT Product_Id FROM MyTable WHERE Product_AttributeID = #parameterValue1) AND Product_Id IN (SELECT Product_Id FROM MyTable WHERE Product_AttributeID = #parameterValue2)
That should do it.
Using proper joins, you can link back to the same table
select B.*
from mytable A
-- retrieve B records from A record link
inner join mytable B on B.product_id = A.product_id
where A.product_attribute_id = 154 -- all the A records
EDIT: to get products that have 2 attributes, you can join another time
select C.*
from mytable A
-- retrieve B records from A record link
inner join mytable B on B.product_id = A.product_id
inner join mytable C on C.product_id = A.product_id
where A.product_attribute_id = 154 -- has attrib 1
AND B.product_attribute_id = 313 -- has attrib 2

Pervasive Sql 10 Join one table, onto another, onto another

I have a table with products.
When I get information from that table, I would also like to get the ETA of that article. To do so, I am planning to get the latest purchase Order Row, that is on this article, and then get the expected delivery of this purchase.
This is three different tables and I would like it to be like another column on the query, so I can get the value from the column like I would if it was on the same table.
Is my idea possible? If there is no purchase order on this article I would like the value to be null.
Products
Int ProductId
Int Price
Sample data
ProductId Price
-----------------
1 100
2 300
PORows
Int RowId
Int ProductId
Int POId
Sample data
RowId ProductId POId
-----------------------
1 1 1
PO
Int POId
DateTime ETA
Sample data
POId ETA
-----------------------
1 2010-10-25 10:05
So the result I would want is:
ProductId Price ETA (null if no rows exist)
------------------------------------------------
1 100 2010-10-25 10:05
2 300 NULL
Use:
SELECT p.productid,
p.price,
x.max_eta
FROM PRODUCTS p
LEFT JOIN POROWS r ON r.productid = p.productid
LEFT JOIN (SELECT po.id,
MAX(po.eta) AS max_eta
FROM PO po
GROUP BY po.id) x ON x.poid = r.poid
Pervasive is the only database I'm aware of that won't allow you to omit the INNER and OUTER keywords. v10 might've relaxed that, but I know it's the case for v8 and 2000.
I don't know Pervasive but in SQL standard you can make the select for the latest PO an aliased subquery
select Products.id, products.name, ProductETAS.ETA
from Products
left join
(
select POLINES.productid, min(PO.ETA) as ETA from PO inner join POLINES
on PO.id = POLINES.POid and POLINES.productid = ?
where PO.ETA >= today
group by POLINES.productid
) as ProductETAS
on Products.productid = ProductETAS.productid