I am trying to add a Sum 'field' to a SELECT query, where it sums up the data on that row, and returns it as a field. The problem seems to lie with the GROUP BY statement, that I seemingly have to use. When using this, it groups the 'sums' together, rather than provides a total for each row of data.
SELECT PS_DB.TeamName AS [Team Name], TM_adjData.SM_adjName AS Adjudicator, PS_DB.WeekEnding AS [Week Ending], PS_DB.Pts AS [BAU Points], PS_DB.Adhc, Sum(PS_DB.Pts + PS_DB.Adhc) as [Total], PS_DB.Approved AS Approved
FROM PS_DB
LEFT JOIN TM_adjData on PS_DB.Adjudicator = TM_adjData.SM_empNum
GROUP BY TeamName, SM_adjName, WeekEnding, Pts, Adhc, Approved
This returns 518 rows, where as if I remove the GROUP BY section and the 'sum' field, it returns 1,608 rows (which is correct).
How can I get the 1,608 rows with the sum next to it?
I think you can do what you want with a correlated subquery:
SELECT p.TeamName AS [Team Name], a.SM_adjName AS Adjudicator,
p.WeekEnding AS [Week Ending], p.Pts AS [BAU Points], p.Adhc,
(SELECT SUM(p2.Pts + p2.Adhc)
FROM PS_DB as p2
WHERE p2.TeamName = p.TeamName -- perhaps more conditions are needed
) as [Total],
p.Approved AS Approved
FROM PS_DB as p LEFT JOIN
TM_adjData as a
ON p.Adjudicator = a.SM_empNum;
If you want to perform a sum for each row, you don't group rows, instead you simply perform addition. I've added Nz() function to properly address issue where any of the value being added is null and treat it as 0:
SELECT
PS_DB.TeamName AS [Team Name],
TM_adjData.SM_adjName AS Adjudicator,
PS_DB.WeekEnding AS [Week Ending],
PS_DB.Pts AS [BAU Points],
PS_DB.Adhc,
Nz(PS_DB.Pts,0) + Nz(PS_DB.Adhc,0) as [Total], -- this is your row sum
PS_DB.Approved AS Approved
FROM PS_DB
LEFT JOIN TM_adjData on PS_DB.Adjudicator = TM_adjData.SM_empNum
SUM is an aggregate function and it works on entire table or groups of data (with GROUP BY).
Related
Feeling a bit confused here, I have a query running against SQL Server where I am trying to return a single row per trans_id and action number (they may be repeated). The trans column would be different in the repeated rows so I only ever want to return the highest (max value) of the trans column to give me the single row per trans_id and action number.
This seems to do the trick:
SELECT DT.trans_id,
MAX(DT.trans),
DA.ACTION_NO,
DT.[Title] AS [Case Title],
DA.[Description] AS [Action Description],
DA.ACTION_TIME_LIMIT AS [Action Deadline],
DA.Performed AS [Action Perfomed]
FROM synergi.stg_D_TRANS DT
INNER JOIN EQDW_Stg.synergi.stg_D_ACTION DA ON DA.TRANS = (SELECT MAX(TRANS)FROM synergi.stg_D_TRANS WHERE trans_id = DT.TRANS_ID)
WHERE DT.TRANS_ID != 0
GROUP BY DT.TRANS_ID,
DA.ACTION_NO,
DT.TITLE,
DA.DESCRIPTION,
DA.PERFORMED,
DA.ACTION_TIME_LIMIT;
However, when I add in this specific column, DT.TRANS_DATE, I get an additional 18 rows because it is returning one of the trans_id with 2 different trans numbers instead of just the rows with the max.
Why would adding in the date column affect this when I have numerous other columns from the same table that adding/removing don't seem to change the result at all.
SELECT DT.trans_id,
MAX(DT.trans),
DA.ACTION_NO,
DT.[Title] AS [Case Title],
DA.[Description] AS [Action Description],
DA.ACTION_TIME_LIMIT AS [Action Deadline],
DA.Performed AS [Action Perfomed],
DT.TRANS_DATE
FROM synergi.stg_D_TRANS DT
INNER JOIN EQDW_Stg.synergi.stg_D_ACTION DA ON DA.TRANS = (SELECT MAX(TRANS)FROM synergi.stg_D_TRANS WHERE trans_id = DT.TRANS_ID)
WHERE DT.TRANS_ID != 0
GROUP BY DT.TRANS_ID,
DA.ACTION_NO,
DT.TITLE,
DA.DESCRIPTION,
DA.PERFORMED,
DA.ACTION_TIME_LIMIT,
DT.TRANS_DATE;
I am trying to run a query to gather the total items on hand in our database. However it seems i'm getting incorrect data. I am selecting selecting just the amount field and summing it using joins from separate tables based on certain parameters, however if I display additional fields such as order number, and date all of a sudden im getting different data, even though those fields are being used as filters in the query. Is it because its not in the select statement? If it needs to be in the select statement is it possible to not display them?
Here are the two queries.
-- Items On Hand
select CONVERT(decimal(25, 2), SUM(tw.amount)) as 'Amt'
from [Sales Header] sh
join
(
select *
from TWAllOrders
where [Status] like 'Released'
) tw
on tw.[Order Nb] = sh.No_
join
(
select *
from OnHand
) oh
on tw.No_ = oh.[Item No_]
where sh.[Requested Delivery Date] < getdate()
HAVING SUM(tw.Quantity) <= SUM(oh.Qty)
providing a sum of 21667457.20
and with the added columns
-- Items On Hand
select CONVERT(decimal(25, 2), SUM(tw.amount)) as 'Amt', [Requested Delivery Date], sh.No_, tw.[Status]
from [Sales Header] sh
join
(
select *
from TWAllOrders
where [Status] like 'Released'
) tw
on tw.[Order Nb] = sh.No_
join
(
select *
from OnHand
) oh
on tw.No_ = oh.[Item No_]
where sh.[Requested Delivery Date] < getdate()
group by sh.[Requested Delivery Date], sh.No_, tw.[Status]
HAVING SUM(tw.Quantity) <= SUM(oh.Qty)
order by sh.[Requested Delivery Date] ASC
Providing a sum of 12319998
I'm self taught in SQL so I may be misunderstanding something obvious, thanks for the help.
With no sample data, I am going to have to demonstrate this in principle. In the latter query you have a GROUP BY meaning the scope of the values in the HAVING will differ, and thus the filtering from said HAVING will be different.
Let's take the following sample data:
CREATE TABLE dbo.MyTable (Grp char(1),
Quantity int,
Required int);
INSERT INTO dbo.MyTable (Grp, Quantity, [Required])
VALUES('a',2,7),
('a',14,2),
('b',4, 7),
('b',3,4),
('c',17,5);
Now we'll perform an overly simplified version of your query:
SELECT SUM(Quantity)
FROM dbo.MyTable
HAVING SUM(Quantity) > SUM(Required);
This brings back the value 40; which is the SUM of all the values in Quantity. A value is returned because the total SUM of Required is 25.
Now let's add a GROUP BY like your second query:
SELECT SUM(Quantity)
FROM dbo.MyTable
GROUP BY Grp
HAVING SUM(Quantity) > SUM(Required);
Now we have 2 rows, with the values 16 and 17 giving a total value of 33. That's because the rows where Grp have a value of 'B' are filtered out, as the SUM of Quantity is lower that Required for 'B'.
The same is happening in your data; in the grouped data you have groups where the HAVING condition isn't met, so those rows aren't returned.
I have a three column table of price breaks called "FPB" that looks like this:
[Part Number] [Quantity] [Price]
AAA-AAAA 100 1.23
AAA-AAAA 200 1.15
BBB-BBBB 100 5.60
CCC-CCCC 500 3.21
....
Where each part number has multiple entries in multiple rows.
I'm trying to reorganize the table to look more like this
[Part Number] [Quantity1] [Price 1] [Quantity 2] [Price 2] [Quantity 3....
AAA-AAAA 100 1.23 200 1.15 ....
BBB-BBBB 100 5.60 ...
CCC-CCCC 500 3.21 ...
...
Where each part number has all its entries combined into one row. The first quantity column should have the lowest available quantity, the second should have the second smallest etc. I am trying to do this by first creating a 1-column table with just the unique part numbers using GROUP BY, and then creating more tables for each column that has the information I want in that column, and then joining it by Part Number. The problem comes when calculating the second smallest quantity for each type, done in the second to last section.
SELECT PNs.[Part Number], Q1T.Q1, P1T.Price, Q2T.Q2
FROM
(SELECT
[Part Number]
FROM FPB
GROUP BY [Part Number]
) AS PNs,
(SELECT
[Part Number],
MIN(Quantity) AS Q1
FROM FPB
GROUP BY [Part Number]
) AS Q1T,
(SELECT
*
FROM FPB
) AS P1T,
(SELECT
[Part Number],
MIN(IIF(Quantity>Q1T.Q1,Quantity)) AS Q2
FROM FPB
GROUP BY [Part Number]
) AS Q2T
WHERE
PNs.[Part Number] = Q1T.[Part Number]
AND P1T.[Part Number] = PNs.[Part Number]
AND P1T.Quantity = Q1T.Q1
AND Q2T.[Part Number] = PNs.[Part Number]
When I run this query, it asks me to enter a parameter value for Q1T.Q1, even though it already exists. If I remove the code section for Q2T, as well as any references to Q2, it will work without a problem, and it won't ask about a value for the other instances of Q1T.Q1. Why doesn't Q1T.Q1 have a value just for that section, and how can I fix it? As a side note, I'm using the SQL features of a program called PHPRunner, and its client doesn't support UPDATE/DELETE/INSERT/CREATE queries, UNION, and DISTINCT.
You're looking for something like this.
select
p1.PartNumber,
ifnull(max(p2.Quantity), 0) + 1 as LowerQuantity,
p1.Quantity as UpperQuantity,
p1.Price,
count(p2.PartNumber) + 1 as PriceTier
from
FPB p1 left outer join FPB p2
on p2.PartNumber = p1.PartNumber and p2.Quantity < p1.Quantity
From there it's easy to pivot in order to insert into a new table:
into into NewFPB (PartNumber, Quantity1, Price1, Quantity2, Price2, ...)
select
PartNumber,
min(switch(PriceTier = 1, UpperQuantity)) as Quantity1,
min(switch(PriceTier = 2, UpperQuantity)) as Quantity2, ...
min(switch(PriceTier = 1, Price)) as Price1,
min(switch(PriceTier = 2, Price)) as Price2, ...
from (
select
p1.PartNumber,
ifnull(max(p2.Quantity), 0) + 1 as LowerQuantity,
p1.Quantity as UpperQuantity,
p1.Price,
count(p2.PartNumber) + 1 as PriceTier
from
FPB p1 left outer join FPB p2
on p2.PartNumber = p1.PartNumber and p2.Quantity < p1.Quantity
) data
You might have to tweak it a little bit for Access to accept it. But the core ideas are there.
The query you call is incorrect.
Q1T is inner select statement , and in Q2T (other inner select statement) , you can't use any field from Q1T
The SQL Server raise error: Incorrect syntax near ')'.
To overcome this limitation , you should use Common Table Expressions CTE
for PNs, Q1T, P1T, Q2T
CTE is like dynamic view.
It's a new feature since sql 2008 and It's a very powerful.
review: https://technet.microsoft.com/en-us/library/ms190766(v=sql.105).aspx
Try to Draw a relational data model for these four CTE to be sure that a relation exist between them based on your where conditions.
I think the logic in this query may raise runtime error during execution:
e.g. The multi-part identifier "Q1T.Q1" could not be bound.
Edit:
For Ms-Access you can create four queries for: PNs, Q1T, P1T, Q2T every one is in a separate query, and the fifth query join these queries and add where conditions.
In this case you will not get any syntax error. and will get Data model with relation free :) .
As per your question, by the time you define the derived table Q2T, Q1T is still an invalid object. You need to try to work around this issue.
EDIT:
Suppose you only got 2-level columns to handle, the code is listed below, i tested it. It works well.
select q5.*,q3.quantity, q3.price
from
(select *
from FPB as Q1
where 0 = (select count(distinct(quantity)) from FPB as Q2 where Q2.quantity < Q1.quantity AND Q2.[part number] = Q1.[part number])) as Q5
,
(
select distinct(temp.[part number]),Q2.quantity, Q2.price from FPB as temp
left join
(select *
from FPB as Q4
where 1 = (select count(distinct(quantity)) from #test as Q2 where Q2.quantity < Q4.quantity AND Q2.[PART NUMBER] = Q4.[PART NUMBER])) as Q2
on temp.[PART NUMBER] = Q2.[PART NUMBER]
) as Q3
where Q5.[PART NUMBER] = Q3.[PART NUMBER]
I have a question about adding a row number over 2 queries.
My query is:
SELECT
'telxm001001' AS Node,
'1' AS [Speed Dialing],
'0' AS [Spd DI Numbers by Range],
NULL as 'Speed Dialing No.',
REPLACE(TelefonGeschaeft, '+', '00') AS [Call Number],
Nachname AS [Directory Name],
Vorname AS [Directory First Name]
FROM
dbo.MaData
WHERE
(TelefonGeschaeft LIKE '+%')
UNION ALL
SELECT
'telxm001001' AS Node,
'1' AS [Speed Dialing],
'0' AS [Spd DI Numbers by Range],
ROW_NUMBER() OVER (ORDER BY Nachname) AS 'Speed Dialing No.',
REPLACE(MobiltelefonGeschaeft, '+', '00') AS [Call Number],
Nachname AS [Directory Name],
Vorname AS [Directory First Name]
FROM
dbo.MaData
WHERE
(MobiltelefonGeschaeft LIKE '+%')
I have a SQL Server table with 1400 entries. The 2 queries brings me the right results but the row numbers are not correct because the numerations Begins at 1 when the second query starts. So in my query result i have a numeration from 1 to 680 and then the numeration Begins at 1 when the second query starts. Is there a way to add a row numbering after the two queries finished so the numeration is from 1 to 1400?
Best regards
switzly
Apply a ROW_NUMBER ordering over a derived query; supply a discriminator (e.g. queryOrder) through the individual queries to keep the relevant results grouped.
SELECT ROW_NUMBER() OVER (ORDER BY queryOrder, [Directory Name]) AS number
FROM (
SELECT 1 AS queryOrder, [Directory Name] ..
UNION ALL
SELECT 2 AS queryOrder, [Directory Name] ..
) j
Before jump into too techie in to this query, do you want to have the row number for both the queries?
If yes, why are you putting NULL in the first query?
If you want to have row number for both the queries, use it on both the queries.
Otherwise, try put them into another query as below:
select
ROW_NUMBER over ..., Node, [Speed Dialing], ....
from
(<actual query here>) as temp1;
Using two tables in MSSQL:
One table, [CUSTOMER], containing information on donors.
- Relevent columns: [CustID], [Name]
One table, [DONATION], containing records for each donation given.
- Relevent columns: [CustID], [Amount], [Date]
The tables share a key, [CustID].
I want to aggregate the [Amounts] according to each [CustID]
SELECT DONATION.CUSTID
,PEOPLE.NAME
,SUM (DONATION.AMOUNT) as TOTAL_DONATION
FROM [dbo].[DONATION] INNER JOIN [dbo].[PEOPLE] ON DONATION.CUSTID = PEOPLE.CUSTID
GROUP BY
DONATION.CUSTID
,PEOPLE.NAME
HAVING SUM (DONATION.AMOUNT) > 100
This query works fine, even with adding the HAVING clause.
When I want to restrict the dates of donations to aggregate (adding to the SELECT,GROUP BY, and HAVING clauses) however...
SELECT DONATION.CUSTID
,PEOPLE.NAME,DONATION.DATE
,SUM (DONATION.AMOUNT) as TOTAL_DONATION
FROM [dbo].[DONATION] INNER JOIN [dbo].[PEOPLE] ON DONATION.CUSTID = PEOPLE.CUSTID
GROUP BY
DONATION.CUSTID
,PEOPLE.NAME
,DONATION.DATE
HAVING SUM (DONATION.AMOUNT) > 100
and DONATION.DATE > '1-1-2010'
The query no longer returns aggregate sums of each person's donations, but returns individual donations for each person, which meet the HAVING criteria.
How can I implement this date restriction? Is it how I'm joining or summing or....? Thanks.
Move it to the WHERE clause
SELECT DONATION.CUSTID
,PEOPLE.NAME
,SUM (DONATION.AMOUNT) as TOTAL_DONATION
FROM [dbo].[DONATION]
INNER JOIN [dbo].[PEOPLE] ON DONATION.CUSTID = PEOPLE.CUSTID
WHERE DONATION.DATE > '1-1-2010'
GROUP BY
DONATION.CUSTID
,PEOPLE.NAME
HAVING SUM (DONATION.AMOUNT) > 100
What this means:
- given the people who donated
- look only at data where donation date is in 2010 or later
- and within that data, show the people who donated a total of more than 100
Modify your first query like:
,SUM (CASE WHEN DONATION.DATE > '1-1-2010' THEN DONATION.AMOUNT END)
as TOTAL_DONATION
You can't group by date unless you want one row per customer per date.
How about doing it from the donation table and just looking up customer names?
select Donator=(select name from [people] where [people].custid=[donation].custid),
custid,SUM(amount)
from [donation]
where [donation].date between '1/1/2011' and '1/15/2011'
group by custid
having SUM(amount)>100