How to correlate update with select query - tsql

I want to update every row in the column SalesDifference20132015 in the table Stockitems based on the values in different columns in the same table. I know the SELECT query work however when I plug it into my update query I get the subquery returned more than 1 value error. How do i correlate my select query with my update?
UPDATE warehouse.StockItems
SET SalesDifference20132015 =
(SELECT (SELECT COUNT(*)
FROM Sales.Orders o
join sales.OrderLines ol ON o.OrderID = ol.OrderID
WHERE ol.StockItemID = si.StockItemID AND YEAR(o.OrderDate) = 2013
Group by ol.StockItemID)
-
(SELECT COUNT(*)
FROM Sales.Orders o
join sales.OrderLines ol ON o.OrderID = ol.OrderID
WHERE ol.StockItemID = si.StockItemID AND YEAR(o.OrderDate) = 2015
Group by ol.StockItemID)
FROM Warehouse.StockItems si
)

Something like this should work:
UPDATE si
SET SalesDifference20132015 = DIFF.Diff
FROM
warehouse.StockItems si
JOIN
(
SELECT DISTINCT
StockItemID
,
(
SELECT COUNT(*)
FROM
Sales.Orders o
JOIN sales.OrderLines ol ON o.OrderID = ol.OrderID
WHERE ol.StockItemID = si.StockItemID AND YEAR(o.OrderDate) = 2013
GROUP BY ol.StockItemID
)
-
(
SELECT COUNT(*)
FROM
Sales.Orders o
JOIN sales.OrderLines ol ON o.OrderID = ol.OrderID
WHERE ol.StockItemID = si.StockItemID AND YEAR(o.OrderDate) = 2015
GROUP BY ol.StockItemID
) Diff
FROM Warehouse.StockItems si
) DIFF
ON si.StockItemID = DIFF.StockItemID

Related

Infinite loop when I updated query to add an additional variable

I have this query:
with users_having_connected as (
select u.id as user_id,
(a.connected_at is not null) has_connected
from core_user u
join core_profile p on u.id = p.user_id
join core_conversation c on (c.profile1_id = p.id or c.profile2_id = p.id)
join analytics_connection a on c.id = a.conversation_id
group by u.id, (a.connected_at is not null)
)
select u.id as user_id,
date_trunc('month', u.created at time zone 'UTC')::date as month,
p.community_id,
p.organization_id,
p.profile_type_intention,
(p.basic_account_completed and (p.is_mentor or p.is_entrepreneur)) as profile_is_completed,
exists(select 1 from core_message where core_message.sender_id = p.id) as has_sent_a_message,
(EXISTS (SELECT 1 FROM core_message WHERE core_message.receiver_id = p.id)) AS has_received_a_message,
(EXISTS (SELECT 1 FROM core_admin_conversation_w_resp WHERE core_admin_conversation_w_resp.initiator_id = p.id or core_admin_conversation_w_resp.responder_id = p.id)) AS has_one_by_one,
exists(select 1 from users_having_connected where user_id = u.id) as has_two_by_two
from core_user as u
join core_profile p on u.id = p.user_id
where
p.profile_type_intention is not null
Which worked fine until I added this line:
(EXISTS (SELECT 1 FROM core_admin_conversation_w_resp WHERE core_admin_conversation_w_resp.initiator_id = p.id or core_admin_conversation_w_resp.responder_id = p.id)) AS has_one_by_one,
This specific variable add causes this query to infinite loop. What do I need to do to fix it? Am I missing a set of parentheses somewhere?

Two columns next to each other from two queries in PostgreSQL

How do I get two columns goed and slecht side by side with the two following queries. They do work independently of each other.
1:
select count (*) as goed
from movie_info_idx mii
join title t
on mii.movie_id = t.id
join info_type it
on it.id = mii.info_type_id
join kind_type kt
on kt.id = t.kind_id
where kt.id = '1'
and it.id = '101'
and mii.info > '7,5'
2:
select count (*) as slecht
from movie_info_idx mii
join title t
on mii.movie_id = t.id
join info_type it
on it.id = mii.info_type_id
join kind_type kt
on kt.id = t.kind_id
where kt.id = '1'
and it.id = '101'
and mii.info <= '7,5'
But how do I merge both queries so I get two columns goed and slecht next to each other?
Conditional aggregation is likely what you're looking for. Here is an example:
SELECT COUNT(*) FILTER (WHERE mii.info > '7,5') AS goed
, COUNT(*) FILTER (WHERE mii.info <= '7,5') AS slecht
FROM movie_info_idx mii
JOIN title t ON mii.movie_id = t.id
JOIN info_type it ON mii.info_type_id = it.id
JOIN kind_type kt ON t.kind_id = kt.id
WHERE kt.id = '1'
AND it.id = '101'
;

View query without sub selecting T-SQL

so I'm trying to build a view query but I keep failing using only joins so I ended up with this deformation.. Any tips on how I can write this query so I don't have to use 6 subselects?
The FeeSum and PaymentSum can be null, so ideally I do not want those in my result set and I also wouldn't like results where the FeeSum and the PaymentSum are equal.
Quick note: client is the table where the clients informations are stored (name, adress, etc..)
customer has a fk on client and is kind of a shell table for the client that store more information for the client,
payment is a list of all payments a customer did,
order is a list of all orders a customer did.
The goal is to get a list where we can track which customer has open fees to pay, based on the orders. It's a legacy project so don't ask why people can order before paying :)
SELECT
cu.Id as [CustomerId]
, CASE
WHEN cl.IsPerson = 1
THEN cl.[AdditionalName] + ' ' + cl.[Name]
ELSE cl.AdditionalName
END as [Name]
, cl.CustomerNumber
, (SELECT SUM(o.Fee) FROM [publication].[Order] o WHERE o.[State] = 2 AND o.CustomerId = cu.Id) as [FeeSum]
, (SELECT SUM(p.Amount) FROM [publication].[Payment] p WHERE p.CustomerId = cu.Id) as [PaymentSum]
, (SELECT MAX(o.OrderDate) FROM [publication].[Order] o WHERE o.[State] = 2 AND o.CustomerId = cu.Id) as [LastOrderDate]
, (SELECT MAX(p.PaymentDate) FROM [publication].[Payment] p WHERE p.CustomerId = cu.Id) as [LastPaymentDate]
, (SELECT MAX(f.Created) FROM [client].[File] f WHERE f.TemplateName = 'Reminder' AND f.ClientId = cl.Id) as [LastReminderDate]
, (SELECT MAX(f.Created) FROM [client].[File] f WHERE f.TemplateName = 'Warning' AND f.ClientId = cl.Id) as [LastWarningDate]
FROM
[publication].[Customer] cu
JOIN
[client].[Client] cl
ON cl.Id = cu.ClientId
WHERE
cu.[Type] = 0
Thanks in advance and I hope I didn't do anything wrong.
Kind regards
You could rewrite the correlated subqueries to instead use joins:
SELECT
cu.Id AS [CustomerId],
CASE WHEN cl.IsPerson = 1
THEN cl.[AdditionalName] + ' ' + cl.[Name]
ELSE cl.AdditionalName END AS [Name],
cl.CustomerNumber,
o.FeeSum,
p.PaymentSum,
o.LastOrderDate,
p.LastPaymentDate,
f.LastReminderDate,
f.LastWarningDate
FROM [publication].[Customer] cu
INNER JOIN [client].[Client] cl
ON cl.Id = cu.ClientId
INNER JOIN
(
SELECT CustomerId, SUM(Fee) AS [FeeSum], MAX(OrderDate) AS [LastOrderDate]
FROM [publication].[Order]
WHERE o.[State] = 2
GROUP BY CustomerId
) o
ON o.CustomerId = cu.Id
INNER JOIN
(
SELECT CustomerId, SUM(Amount) AS [PaymentSum], MAX(PaymentDate) AS [LastPaymentDate]
FROM [publication].[Payment]
WHERE o.[State] = 2
GROUP BY CustomerId
) p
ON p.CustomerId = cu.Id
INNER JOIN
(
SELECT ClientId,
MAX(CASE WHEN TemplateName = 'Reminder' THEN Created END) AS [LastReminderDate],
MAX(CASE WHEN TemplateName = 'Warning' THEN Created END) AS [LastWarningDate]
FROM [client].[File]
GROUP BY ClientId
) f
ON f.ClientId = cl.Id
WHERE
cu.[Type] = 0;

Trying to . convert a value to a name during output

the values returned in column a.user_id are id numbers. I would like to return them as a name or initials e.g. 1 = Chris O or C.ONeill
I have tried CASE function but did not know where to put it
SELECT DISTINCT
sb.start_time::date AS shift_date,
i.title AS industry,
wl.name AS venue_name,
w.first_name,
w.last_name,
MIN(cs.start_time::date) AS first_completed_shift,
i.title AS industry,
w.interviewed_on AS induction_date,
d.issue_date AS edbs_issue_date,
d.created_at AS date_dbs_added,
a.user_id --IS IT POSSIBLE TO GET THESE AS VALUES,e.g. a.user_id '1' = 'Chris O or C.ONeill' USING USER NAMES INSTEAD OF USER ID?
FROM shift_bookings sb
JOIN jobs j ON sb.job_id = j.id
JOIN listings l ON j.listing_id = l.id
JOIN work_locations wl ON l.venue_id = wl.id
JOIN workers w ON sb.worker_id = w.id
JOIN completed_shifts cs ON w.id = cs.worker_id
JOIN documents d ON w.id = d.documentable_id
JOIN audits a ON d.id = a.auditable_id
JOIN industries i ON j.industry_id = i.id
WHERE sb.shift_id IN (253106)
AND d.document_type_id = 33
AND a.auditable_type = 'Document'
GROUP BY
sb.start_time::date,
wl.name,
w.first_name,
w.last_name,
i.title,
w.interviewed_on,
d.issue_date,
d.created_at,
a.user_id
a.user_id output will be something else I can set

Grades of each quiz in Moodle

I'm trying to get grades of each question, I have a query but it only return final grade of whole exam, but i want grade of each question, how to get it?
Here is query that i have:
SELECT mdl_grade_items.id AS ItemID,
mdl_course.shortname AS CourseShortname,
mdl_grade_items.itemname AS ItemName,
mdl_grade_items.grademax AS ItemGradeMax,
mdl_grade_items.aggregationcoef AS ItemAggregation,
mdl_grade_grades.finalgrade AS FinalGrade,
mdl_user.username AS StudentID,
mdl_user.id
FROM mdl_grade_items
INNER JOIN mdl_grade_grades
ON mdl_grade_items.id = mdl_grade_grades.itemid
INNER JOIN mdl_role_assignments
ON mdl_grade_grades.userid = mdl_role_assignments.userid
AND mdl_grade_items.courseid = mdl_role_assignments.mdlcourseid
INNER JOIN mdl_course
ON mdl_course.id = mdl_grade_items.courseid
INNER JOIN mdl_user
ON mdl_user.id = mdl_role_assignments.userid
Ok, i found it
SELECT mqa.id,meqi.grade * (select fraction from mdl_question_attempt_steps where
questionattemptid = mqas.questionattemptid and state like 'mangr%' order by id desc limit
1 ) finalgrade,me.course , mqas.userid,u.firstname, u.lastname, mqa.questionsummary,
mqa.responsesummary , meqi.grade
FROM mdl_question_attempts mqa
left JOIN mdl_question_attempt_steps mqas ON mqa.id = mqas.questionattemptid
left JOIN mdl_user u ON mqas.userid = u.id
left JOIN mdl_examm_question_instances meqi ON meqi.question = mqa.questionid
left JOIN mdl_examm me ON meqi.examm = me.id
WHERE me.course= $courseID and userid = $userID