PSQL: sum doesn't work on fields - sql

I have this query which works:
SELECT
partners.name,
roles.name,
(SELECT count(*) FROM partner_member_bindings WHERE roles.id = partner_member_bindings.role_id AND verify_status != 'pending') AS Num_verifications,
CAST(roles.price_partner / 100 AS money) AS partner_price
FROM partners
JOIN roles ON roles.partner_id = partners.id
ORDER BY partners.name, roles.name
What I want is to display an additional field showing the "partner_price * Num_verifications" value in dollars. Nothing I do works:
sum(Num_verifications * partner_price) returns that the Num_verification doesn't exist. Copying over the whole sub-query (yes, i know, but I'm just testing) also doesn't work.
How can this be done?

The fields in select can only contain input columns and they become output columns when they are run. That is why you cannot use a computed column in another column definition.
But if you want a SUM that would mean some kind of aggregation. If you want the total sum of the multiplication of the fields, that is not usually done per row. Or do you only need the multiplication result? That is usually done in the presentation layer.
If you only need the multiplication (since there is no GROUP BY the SUM would be that anyway) you can put the whole query into a subquery and calculate from that, leaving the sorting outside:
SELECT
partnername,
rolename,
Num_verifications,
partner_price,
partner_price*Num_verifications
FROM
(SELECT
partners.name as partnername,
roles.name as rolename,
(SELECT count(*) FROM partner_member_bindings WHERE roles.id = partner_member_bindings.role_id AND verify_status != 'pending') AS Num_verifications,
CAST(roles.price_partner / 100 AS money) AS partner_price
FROM partners
JOIN roles ON roles.partner_id = partners.id) temp
ORDER BY partners.name, roles.name

Related

SQL - Returning fields based on where clause then joining same table to return max value?

I have a table named Ticket Numbers, which (for this example) contain the columns:
Ticket_Number
Assigned_Group
Assigned_Group_Sequence_No
Reported_Date
Each ticket number could contain 4 rows, depending on how many times the ticket changed assigned groups. Some of these rows could contain an assigned group of "Desktop Support," but some may not. Here is an example:
Example of raw data
What I am trying to accomplish is to get the an output that contains any ticket numbers that contain 'Desktop Support', but also the assigned group of the max sequence number. Here is what I am trying to accomplish with SQL:
Queried Data
I'm trying to use SQL with the following query but have no clue what I'm doing wrong:
select ih.incident_number,ih.assigned_group, incident_history2.maxseq, incident_history2.assigned_group
from incident_history_public as ih
left join
(
select max(assigned_group_seq_no) maxseq, incident_number, assigned_group
from incident_history_public
group by incident_number, assigned_group
) incident_history2
on ih.incident_number = incident_history2.incident_number
and ih.assigned_group_seq_no = incident_history2.maxseq
where ih.ASSIGNED_GROUP LIKE '%DS%'
Does anyone know what I am doing wrong?
You might want to create a proper alias for incident_history. e.g.
from incident_history as incident_history1
and
on incident_history1.ticket_number = incident_history2.ticket_number
and incident_history1.assigned_group_seq_no = incident_history2.maxseq
In my humble opinion a first error could be that I don't see any column named "incident_history2.assigned_group".
I would try to use common table expression, to get only ticket number that contains "Desktop_support":
WITH desktop as (
SELECT distinct Ticket_Number
FROM incident_history
WHERE Assigned_Group = "Desktop Support"
),
Than an Inner Join of the result with your inner table to get ticket number and maxSeq, so in a second moment you can get also the "MAXGroup":
WITH tmp AS (
SELECT i2.Ticket_Number, i2.maxseq
FROM desktop D inner join
(SELECT Ticket_number, max(assigned_group_seq_no) as maxseq
FROM incident_history
GROUP BY ticket_number) as i2
ON D.Ticket_Number = i2.Ticket_Number
)
SELECT i.Ticket_Number, i.Assigned_Group as MAX_Group, T.maxseq, i.Reported_Date
FROM tmp T inner join incident_history i
ON T.Ticket_Number = i.Ticket_Number and i.assigned_group_seq_no = T.maxseq
I think there are several different method to resolve this question, but I really hope it's helpful for you!
For more information about Common Table Expression: https://www.essentialsql.com/introduction-common-table-expressions-ctes/

Select only the row with the max value, but the column with this info is a SUM()

I have the following query:
SELECT DISTINCT
CAB.CODPARC,
PAR.RAZAOSOCIAL,
BAI.NOMEBAI,
SUM(VLRNOTA) AS AMOUNT
FROM TGFCAB CAB, TGFPAR PAR, TSIBAI BAI
WHERE CAB.CODPARC = PAR.CODPARC
AND PAR.CODBAI = BAI.CODBAI
AND CAB.TIPMOV = 'V'
AND STATUSNOTA = 'L'
AND PAR.CODCID = 5358
GROUP BY
CAB.CODPARC,
PAR.RAZAOSOCIAL,
BAI.NOMEBAI
Which the result is this. Company names and neighborhood hid for obvious reasons
The query at the moment, for those who don't understand Latin languages, is giving me clients, company name, company neighborhood, and the total value of movements.
in the WHERE clause it is only filtering sales movements of companies from an established city.
But if you notice in the Select statement, the column that is retuning the value that aggregates the total amount of value of sales is a SUM().
My goal is to return only the company that have the maximum value of this column, if its a tie, display both of em.
This is where i'm struggling, cause i can't seem to find a simple solution. I tried to use
WHERE AMOUNT = MAX(AMOUNT)
But as expected it didn't work
You tagged the question with the whole bunch of different databases; do you really use all of them?
Because, "PL/SQL" reads as "Oracle". If that's so, here's one option.
with temp as
-- this is your current query
(select columns,
sum(vrlnota) as amount
from ...
where ...
)
-- query that returns what you asked for
select *
from temp t
where t.amount = (select max(a.amount)
from temp a
);
You should be able to achieve the same without the need for a subquery using window over() function,
WITH T AS (
SELECT
CAB.CODPARC,
PAR.RAZAOSOCIAL,
BAI.NOMEBAI,
SUM(VLRNOTA) AS AMOUNT,
MAX(VLRNOTA) over() AS MAMOUNT
FROM TGFCAB CAB
JOIN TGFPAR PAR ON PAR.CODPARC = CAB.CODPARC
JOIN TSIBAI BAI ON BAI.CODBAI = PAR.CODBAI
WHERE CAB.TIPMOV = 'V'
AND STATUSNOTA = 'L'
AND PAR.CODCID = 5358
GROUP BY CAB.CODPARC, PAR.RAZAOSOCIAL, BAI.NOMEBAI
)
SELECT CODPARC, RAZAOSOCIAL, NOMEBAI, AMOUNT
FROM T
WHERE AMOUNT=MAMOUNT
Note it's usually (always) beneficial to join tables using clear explicit join syntax. This should be fine cross-platform between Oracle & SQL Server.

mSSQL, SQL view, select, percentage query

So this is the requirement I need to meet:
Aggregated data of all the schools in the ESD, grouped by
SchoolDistrict.SchoolDistrictID
(get the same data as the school district scenario above, then add grouping by district, filtered to
EducationServiceDistrict. EducationServiceDistrictID
)
Also calculate percentage of pass, fail, and untested
How do I calculate the percentage pass, fail, and untested?
This is the query I have written so far.
CREATE VIEW district_map AS
SELECT * and SchoolDistrictID,
EducationServiceDistrict
FROM SchoolDistrict_View
and SchoolDistrict,
EducationServiceDistrict
GROUP BY EducationServiceDistrict.EducationServiceDistrictID
ORDER BYLeadWaterTestLocation.PassFail
This is the general idea of how these problems are solved - if you understand this simplified version you will be able to solve your problem.
select d.districtName,
s.studentCount,
case when s.studentCount=0 then 0 else s.passed / s.studentCount * 100 end as PassedPct
from district d
join (select districtId,
sum(studentCount) as studentCount,
sum(passed) as passed
from schools
group by districtId) as s
on d.districtId = s.districtId
order by d.districtName

Total price from different tables

I have a database with customers, items and orders. This is an exam project, so is maybe not the best for real life. I have this problem. I want a list of what all our customers have bought and a total price of that, but I can't get anything to work.
select Kunder.navn,Ordre.*, Indeholder.antal, Varer.*
from Kunder
join Ordre on Kunder.kunde_nr=Ordre.kunde_nr
join Indeholder on Ordre.ordre_nr=Indeholder.ordre_nr
join Varer on Varer.vare_nr=Indeholder.vare_nr
where er_industri=0
order by bestillingsdato
I have tried a lot like:
sum (Indeholder.antal * Varer.privat_pris) as total
group by Ordre.ordre_nr
But I just can't get anything that I've tried, to give me what I'm looking for.
I hope that you want to help me, and that you understand what I mean (I'm not a native english speaker).
I have uploaded an image of our mapping, so you can see what our database look like:
And for clarity, just a translation:
Kunder = customers
Varer = items
Ordre = orders
Indeholder = includes
Just add more columns on your group by clause.
Apart from the aggregate functions [SUM(), COUNT(), AGV()] the same list of columns must be present at the group by clause
and at select clause:
So, generally:
select <col1, col2, col3...>, SUM(...)
from ...
group by <col1, col2, col3...>
If you want a per customer AND order groupping:
select Kunder.navn, Ordre.ordre_nr, sum (Indeholder.antal * Varer.privat_pris) as total
from Kunder
join Ordre on Kunder.kunde_nr=Ordre.kunde_nr
join Indeholder on Ordre.ordre_nr=Indeholder.ordre_nr
join Varer on Varer.vare_nr=Indeholder.vare_nr
where er_industri=0
group by Kunder.navn, Ordre.ordre_nr
You could also do a per customer groupping:
select Kunder.navn, sum (Indeholder.antal * Varer.privat_pris) as total
from Kunder
join Ordre on Kunder.kunde_nr=Ordre.kunde_nr
join Indeholder on Ordre.ordre_nr=Indeholder.ordre_nr
join Varer on Varer.vare_nr=Indeholder.vare_nr
where er_industri=0
group by Kunder.navn

How do you explicitly show rows which have count(*) equal to 0

The query I'm running in DB2
select yrb_customer.name,
yrb_customer.city,
CASE count(*) WHEN 0 THEN 0 ELSE count(*) END as #UniClubs
from yrb_member, yrb_customer
where yrb_member.cid = yrb_customer.cid and yrb_member.club like '%Club%'
group by yrb_customer.name, yrb_customer.city order by count(*)
Shows me people which are part of clubs which has the word 'Club' in it, and it shows how many such clubs they are part of (#UniClubs) along with their name and City. However for students who are not part of such a club, I would still like for them to show up but just have 0 instead of them being hidden which is what's happening right now. I cannot get this functionality with count(*). Can somebody shed some light? I can explain further if the above is not clear enough.
I'm not familiar with DB2 so I'm taking a stab in the dark, but try this:
select yrb_customer.name,
yrb_customer.city,
CASE WHEN yrb_member.club like '%Club% THEN count(*) ELSE 0 END as #UniClubs
from yrb_member, yrb_customer
where yrb_member.cid = yrb_customer.cid
group by yrb_customer.name, yrb_customer.city order by count(*)
Basically you don't want to filter for %Club% in your WHERE clause because you want ALL rows to come back.
You're going to want a LEFT JOIN:
SELECT yrb_customer.name, yrb_customer.city,
COUNT(yrb_member.club) as clubCount
FROM yrb_customer
LEFT JOIN yrb_member
ON yrb_member.cid = yrb_customer.cid
AND yrb_member.club LIKE '%Club%
GROUP BY yrb_customer.name, yrb_customer.city
ORDER BY clubCount
Also, if the tuple (yrb_customer.name, yrb_customer.city) is unique (or is supposed to be - are you counting all students with the same name as the same person?), you might get better performance out of the following:
SELECT yrb_customer.name, yrb_customer.city,
COALESCE(club.count, 0)
FROM yrb_customer
LEFT JOIN (SELECT cid, COUNT(*) as count
FROM yrb_member
WHERE club LIKE '%Club%
GROUP BY cid) club
ON club.cid = yrb_customer.cid
ORDER BY club.count
The reason that your original results were being hidden was because in your original query, you have an implicit inner join, which of course requires matching rows. The implicit-join syntax (comma-separated FROM clause) is great for inner (regular) joins, but is terrible for left-joins, which is what you really needed. The use of the implicit-join syntax (and certain types of related filtering in the WHERE clause) is considered deprecated.