I have the following example code:
create table Details(
name varchar(20),
age int,
weight int,
recordDate Datetime)
--insert data
..query:
SELECT a.name,
a.age,
a.recordDate,
a.weight - (SELECT b.weight
FROM Details
WHERE b.recordDate = dateadd(dd, -1, a.recordDate) as subtable)
FROM Details a
GROUP BY WITH ROLLUP (a.recordDate, a.name, a.age)
I want to see the weight difference between RecordDates for each person and then record total weight different for that person and also for the age group and then grand weight gain/loss. This is not my actual table but just an example.
Problem:
It was complaining about subquery - then I had to use it as table variable: subtable.
Now it is complaining:
Msg 156, Level 15, State 1, Line 14
Incorrect syntax near the keyword 'as'.
Msg 319, Level 15, State 1, Line 18
Incorrect syntax near the keyword 'with'. If this statement is a common table expression or an xmlnamespaces clause, the previous statement must be terminated with a semicolon.
What am I missing?
Typo:
a.weight - (SELECT b.weight
FROM Details
WHERE b.recordDate = dateadd(dd, -1, a.recordDate)
..."b" is being used as a table alias, but it's not actually defined as one.
Next issue is that your GROUP BY doesn't include a.weight, and there's no aggregate function associated with it. Here's my re-write of your query:
SELECT a.name,
a.age,
a.recordDate,
SUM(a.weight - t.weight) 'weight'
FROM DETAILS a
JOIN (SELECT b.recordDate,
b.weight
FROM DETAILS b) t ON t.recordDate = DATEADD(dd, -1, a.recordDate)
GROUP BY (a.recordDate, a.name, a.age) WITH ROLLUP
Try it like this
SELECT
a.name,
a.age,
a.recordDate,
SUM(a.weight - b.weight) as WeightDiff
FROM Details a
JOIN Details b
ON (b.age = a.age
AND b.name = a.name
AND b.recordDate = dateadd(dd, -1, a.recordDate)
)
GROUP BY a.age, a.name, a.recordDate WITH ROLLUP
Don't use AS keyword. You can just directly write {(select * from blah) a}
OK, so the problem is that WITH ROLLUP isn't really the answer you're looking for. This is for creating subtotals not running totals which is what you're after, so using it will give you the total for different combinations of dates rather than a running total, which is what you're after. In the beginning, the query that you want to just get a total that gives you name, age, date and weight loss compared to yesterday is as follows:
select
a.name
,a.age
,a.recordDate
,(SELECT b.weight from Details b WHERE b.recordDate = dateadd(dd,-1,a.recordDate)) - a.weight as weightLossForToday
from details a
Keep in mind that this query will only work if you have exactly 1 record every day. If you have 2 records for a single day or the entries aren't exactly 1 day apart (ie. they include time), then it won't work. In order to get a running total working, you'll need to follow the approach from a question like this.
That should do the trick.
SELECT a.name,a.age,a.recordDate,a.weight-(SELECT b.weight
FROM Details
WHERE b.recordDate=dateadd(dd,-1,a.recordDate))
FROM Details a
GROUP BY (a.recordDate,a.name,a.age)
WITH ROLLUP
Related
I need to perform multiple JOINs, I am grabbing the data from multiple tables and JOINing on id. The tricky part is that one table I need to join twice. Here is the code:
(
SELECT
content.brand_identifier AS brand_name,
CAST(timestamp(furniture.date) AS DATE) AS order_date,
total_hearst_commission
FROM
`furniture_table` AS furniture
LEFT JOIN `content_table` AS content ON furniture.site_content_id = content.site_content_id
WHERE
(
timestamp(furniture.date) >= TIMESTAMP('2020-06-01 00:00:00')
)
)
UNION
(
SELECT
flowers.a_merchant_name AS merchant_name
FROM
`flowers_table` AS flowers
LEFT JOIN `content` AS content ON flowers.site_content_id = content.site_content_id
)
GROUP BY
1,
2,
3,
4
ORDER BY
4 DESC
LIMIT
500
I thought I could use UNION but it gives me an error Syntax error: Expected keyword ALL or keyword DISTINCT but got "("
I'm not able to comment, but like GHB states, the queries do not have the same number of columns; therefore, UNION will not work here.
I think it would be helpful to know why sub-queries are needed in the first place. I'm guessing this query does not product the results you want, so please elaborate on why that is.
select
f.a_merchant_name as merchant_name,
c.brand_identifier as brand_name,
CAST(timestamp(f.date) AS DATE) AS order_date,
total_hearst_commission
from furniture_table f
left join content_table c on c.site_content_id = f.site_content_id
where timestamp(f.date) >= TIMESTAMP('2020-06-01 00:00:00')
group by 1,2,3,4
Thanks to the input I've received earlier on this site, I use the below code to summarize how many months of experience our employees have in a specific market.
The issue however is that the end-result shows the summarized data for all employees, even if they no longer work for our company. What I actually would like, is the same output, but then only for those employees who are still present in the youngest date (SNAPSHOT_DATE).
I managed to get to a solution where I manually update the snapshot every month, but I'd rather go for an automated solution where the code itself determines what the youngest snapshot is.
Many thanks for your support :)
SELECT EMPLOYEE_ID,
ISNULL([Developing & Emerging],0) AS [Experience - D&E],
ISNULL([Developed],0) AS [Experience - D]
FROM
(
SELECT EMPLOYEE_ID,MARKET_TYPE_DESC,COUNT(SNAPSHOT_DATE) T
FROM [db_name].[AGL_V_HRA_FE_R].[VW_HRA_EMPLOYEE_DETAIL]
WHERE ALLC_SER_NUM = '1'
GROUP BY EMPLOYEE_ID,MARKET_TYPE_DESC
)P
PIVOT(
SUM(T)
FOR MARKET_TYPE_DESC IN ([Developing & Emerging],[Developed])
)PVT
It sounds like you are trying to reduce your query down to only return results where [db_name].[AGL_V_HRA_FE_R].[VW_HRA_EMPLOYEE_DETAIL].SNAPSHOT_DATE == the latest snapshot date.
There are multiple ways you can achieve this, but probably the simplest and most easily readable would be something like the following:
DECLARE #SnapshotDate DATETIME
SELECT #SnapshotDate = MIN(SNAPSHOT_DATE ) FROM [db_name].[AGL_V_HRA_FE_R].[VW_HRA_EMPLOYEE_DETAIL]
And then use a CTE to reduce the included list of employees to only those which have a record which matches this snapshot date, by joining the CTE in your main query:
;WITH CTE AS
(
SELECT EMPLOYEE_ID
FROM [db_name].[AGL_V_HRA_FE_R].[VW_HRA_EMPLOYEE_DETAIL]
WHERE SNAPSHOT_DATE = #SnapshotDate
)
SELECT EMPLOYEE_ID,
ISNULL([Developing & Emerging],0) AS [Experience - D&E],
ISNULL([Developed],0) AS [Experience - D]
FROM
(
SELECT ED.EMPLOYEE_ID,ED.MARKET_TYPE_DESC,COUNT(ED.SNAPSHOT_DATE) T
FROM [db_name].[AGL_V_HRA_FE_R].[VW_HRA_EMPLOYEE_DETAIL] ED
JOIN CTE C ON C.EMPLOYEE_ID = ED.EMPLOYEE_ID
WHERE ED.ALLC_SER_NUM = '1'
GROUP BY ED.EMPLOYEE_ID,ED.MARKET_TYPE_DESC
)P
PIVOT(
SUM(T)
FOR MARKET_TYPE_DESC IN ([Developing & Emerging],[Developed])
)PVT
Thanks, #James S! Much appreciated :)
Perhaps a stupid question, but should I just create one query combining both your inputs? Looking like the one below?
DECLARE #SnapshotDate DATETIME
SELECT #SnapshotDate = MIN(SNAPSHOT_DATE ) FROM [db_name].[AGL_V_HRA_FE_R].[VW_HRA_EMPLOYEE_DETAIL]
WITH CTE AS
(
SELECT EMPLOYEE_ID
FROM [db_name].[AGL_V_HRA_FE_R].[VW_HRA_EMPLOYEE_DETAIL]
WHERE SNAPSHOT_DATE = #SnapshotDate
)
SELECT EMPLOYEE_ID,
ISNULL([Developing & Emerging],0) AS [Experience - D&E],
ISNULL([Developed],0) AS [Experience - D]
FROM
(
SELECT EMPLOYEE_ID,MARKET_TYPE_DESC,COUNT(SNAPSHOT_DATE) T
FROM [db_name].[AGL_V_HRA_FE_R].[VW_HRA_EMPLOYEE_DETAIL] ED
JOIN CTE C ON C.EMPLOYEE_ID = ED.EMPLOYEE_ID
WHERE ALLC_SER_NUM = '1'
AND SNAPSHOT_DATE = #SnapshotDate
GROUP BY EMPLOYEE_ID,MARKET_TYPE_DESC
)P
PIVOT(
SUM(T)
FOR MARKET_TYPE_DESC IN ([Developing & Emerging],[Developed])
)PVT
I tried this, but it seems that doesn't work as it gives the following reply:
Incorrect syntax near 'CTE'. If this is intended to be a common table expression, you need to explicitly terminate the previous statement with a semi-colon.```
I cannot solve a problem with my GROUP BY problem in my query containing CASE...WHEN
Could you help me please with that?
select ID,
CODE,
NOM AS TITLE,
level,
ID_PARENT,
CASE ID_PARENT
WHEN 1111 THEN 'MAIN'
ELSE
(
SUBSTR(
(
SELECT CODE FROM units o
INNER JOIN LIB_UNITS_MV oLab on oLab.ID = o.ID WHERE o.ID = units.ID_PARENT AND LNG_CD = 'ENG'
)
, 7)
)
END AS "PARENT_CODE"
from units
INNER JOIN LIB_UNITS_MV orgLab on orgLab.ID = units.ID
WHERE orgLab.LNG ='ENG'
start with units.id = 1111
connect by prior u.ID = u.ID_PARENT
GROUP BY ID, CODE, NOM, level, ID_PARENT
I obtain the error "not a GROUP BY expression" because I have the WHEN...CASE
Thank you in advance for your help
Regards
Becuase when you group by you need to group by sufficient number of columns, which you use in select statement, outside aggregating functions (min, max, sum etc). So in your case this means - you can either group by all columns used in your case statement, or group by the whole case statement (just copy it over to your group by), or any set of sub-combinations of the whole case, altogether covering it completely. However - since you are not using any aggregate functions I would just do distinct and drop group by altogether.
Why this query is not working:-
SELECT b.byhub,
Count(awbno)
FROM (SELECT awbno,
byhub,
entrydatetime,
Max(entrydatetime)
FROM wbbooking
GROUP BY awbno,
byhub,
entrydatetime) B
INNER JOIN (SELECT refno,
Max(entrydatetime)
FROM wbmmreceiving
GROUP BY refno) R
ON B.awbno = R.refno
WHERE CONVERT(DATE, b.entrydatetime) BETWEEN '2016-10-13' AND '2016-10-13'
GROUP BY b.byhub
After Execute this query I have obtain this type of Error:-
Msg 8155, Level 16, State 2, Line 2
No column name was specified for column 4 of 'b'.
Msg 8155, Level 16, State 2, Line 3
No column name was specified for column 2 of 'r'.
The errors occur, because you have not specified a name for the aggregate column Max(entrydatetime). Change it to Max(entrydatetime) AS max_entrydatetime.
This query is a bit strange. The subquery B selects entrydatetime as well as Max(entrydatetime). But since entrydatetime is included in the group by list, Max(entrydatetime) will always be the same as entrydattetime.
If you want the last entrydatetime per awbno and byhub, then don't group by entrydatetime and only include it as Max(entrydatetime) in the select list. If you really want to group by this date column, then don't include it as Max(entrydatetime).
What is the purpose of the second subquery? None of its returned columns are used except for joining. Is it needed for the count?
Why include a where-clause in the outer query? If you include it in the first subquery, it is more efficient and the entrydatetime column needs not to be returned any more.
Just specify column names for your subqueries, like this:
SELECT b.byhub,
Count(awbno)
FROM (SELECT awbno,
byhub,
entrydatetime,
Max(entrydatetime) max_entrydatetime
FROM wbbooking
GROUP BY awbno,
byhub,
entrydatetime) B
INNER JOIN (SELECT refno,
Max(entrydatetime) max_entrydatetime
FROM wbmmreceiving
GROUP BY refno) R
ON B.awbno = R.refno
WHERE CONVERT(DATE, b.entrydatetime) BETWEEN '2016-10-13' AND '2016-10-13'
GROUP BY b.byhub
I have this query, and I want to get the results of both of these queries. Note that machine_output is a view I created :
SELECT DISTINCT tblcertified.employeenumber,
tblcertified.machinenumber
FROM tblcertified
INNER JOIN machine_output
ON tblcertified.machinenumber = machine_output.machinenumber
UNION
SELECT CONVERT (DATE, tblperiod.fromdate) AS fDate,
tblscheduled.employeenumber
FROM tblperiod
INNER JOIN tblscheduled
ON tblperiod.number = tblscheduled.number
WHERE tblperiod.fromdate BETWEEN Dateadd(m, -3, Getdate()) AND Getdate()
When running the above, I get the following error:
Msg 241, Level 16, State 1, Line 1 Conversion failed when converting
date and/or time from character string.
I also get this error when I drop the convert statement.
Your first column in the first subquery is called EmployeeNumber.
Your first column in the second table is being converted to Date.
I don't think you want a union, but you are familiar with joins. Your select lists needs to match for a union.
If you want to fix this, change the first select to something like:
select distinct cast(NULL as date) as fDate, tblcertified.employeenumber, tblcertified.machinenumber
and the second select to something like:
SELECT CONVERT (DATE, tblperiod.fromdate) AS fDate,
tblscheduled.employeenumber , NULL
As a join, your query would look something like this:
SELECT DISTINCT CONVERT (DATE, tblperiod.fromdate) AS fDate, tblcertified.employeenumber,
tblcertified.machinenumber
FROM tblcertified
INNER JOIN machine_output
ON tblcertified.machinenumber = machine_output.machinenumber
INNER JOIN tblscheduled
on tblscheduled.employeenumber = tblcertified.employeenumber
INNER JOIN tblperiod
ON tblperiod.number = tblscheduled.number
WHERE tblperiod.fromdate BETWEEN Dateadd(m, -3, Getdate()) AND Getdate() ;
This is a bit of guess as to what you want (you have no sample data to make it clear). But, you can do all the joins in one query and pull out the columns you need.