What is wrong with the structure of this nested query? [closed] - sql

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am using SQL Server 2014 and I have the following T-SQL query:
SELECT
COUNT (xx.[Email]), xx.[StayID]
FROM
(SELECT
COUNT (x.[RepID]),x.[StayID], x.[Email], x.[RepID]
FROM
(SELECT
*,
([Email] + CONVERT(VARCHAR(10), [Arrival Date], 20)) AS 'RepID'
FROM [Table1]
WHERE [Arrival Date] BETWEEN '2015-07-01' AND '2018-06-30'
AND [Email] <> '') x
GROUP BY
x.[StayID], x.[Email], x.[RepID]
HAVING
COUNT(x.[RepID]) > 1) xx
GROUP BY
xx.[StayID], xx.[Email]
HAVING
COUNT(xx.[Email]) > 1
I am getting the following error message:
No column name was specified for column 1 of 'xx'.
What am I doing wrong here?
I was also looking at changing the query into a CTE. Would that be a solution?

Try this - Modified your query and given the name to xx first column (RepIdCount):
SELECT COUNT (xx.[Email]), xx.[StayID]
FROM (
SELECT COUNT (x.[RepID]) as RepIDCount, x.[StayID], x.[Email], x.[RepID]
FROM (
SELECT *, ([Email] + CONVERT(varchar(10), [Arrival Date], 20)) as 'RepID'
FROM [Table1]
WHERE [Arrival Date] between '2015-07-01' and '2018-06-30'
AND [Email] <> ''
) x
GROUP BY x.[StayID], x.[Email], x.[RepID]
Having Count(x.[RepID]) > 1
) xx
GROUP BY xx.[StayID], xx.[Email]
Having Count(xx.[Email]) > 1

I would say you rewrite the query in a better way, but the issue in your query is in the below line
SELECT COUNT (x.[RepID]), x.[StayID], x.[Email], x.[RepID]
you either remove the COUNT (x.[RepID]) statement since its not used in your parent Select statement or you an give an alias like below
SELECT COUNT (x.[RepID]) as RepCount, x.[StayID], x.[Email], x.[RepID]

If you run this simple query:
select count(*) from some_table
you will notice the result set in the output will have a column name of "No column name".
SQL server does not generate a default column name for aggregate functions.
Thus, the first (and only) column of table xx, i.e.
COUNT (x.[RepID]),x.[StayID], x.[Email], x.[RepID]
has no name. You may not have a subquery that included unnamed columns. give it a name:
COUNT (x.[RepID]) as cnt ,x.[StayID], x.[Email], x.[RepID])
By the way, why go in the trouble of typing all the column names in the COUNT?
Could it be you

Related

SQL Question : Technical question that requires you to answer How many members worked at IBM before working at Google? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 months ago.
Improve this question
Assume the following dataset:
member_id
company
Year_started
1
Apple
2001
1
IBM
2002
1
Oracle
2005
1
Microsoft
2010
2
IBM
2002
2
Microsoft
2004
2
Oracle
2008
Member 1, began work at IBM in 2002, moved to Oracle in 2005 and moved to Microsoft in 2010. Member 2, began workin gat IBM in 2002, moved to Microsoft in 2004 and then Moved to oracle in 2008. Assume that for each member in each year, there is only one company (cannot work at 2 different companies in the same year).
**Question: How many members ever worked at IBM prior to working at Oracle? **
How would you go about solving this? I tried a combination of CASE when's but am lost as to where else to go. Thanks.
...
..
I would phrase this using EXISTS:
SELECT DISTINCT member_id
FROM yourTable t1
WHERE company = 'Google' AND
EXISTS (SELECT 1 FROM yourTable t2
WHERE t2.member_id = t1.member_id AND
t2.company = 'IBM' AND
t2.Year_started < t1.Year_started);
In plain English, the above query says to report every employee who worked at Google in some year, for which there is a record from an earlier year for the same employee who worked at IBM at that time.
I would go for querying the table twice and then join like so:
select count(*)
from (
select member_id, min(Year_started) y
from my_table
where company = 'IBM'
group by member_id
) i
join (
select member_id, max(Year_started) y
from my_table
where company = 'Oracle'
group by member_id
) o on i.member_id = o.member_id and i.y < o.y
Note the difference of min/max functions on the year column. This would yield a match for the use case Oracle-IBM-Oracle as well as IBM-Oracle-IBM.
Simply do a self join:
select count(distinct m1.member_id)
from members m1
join members m2
on m1.member_id = m2.member_id and m1.Year_started < m2.Year_started
where m1.company = 'IBM' and m2.company = 'Oracle';
More verbose, but using CTEs:
For each member_id, get the first year they worked at IBM (if any), and get the first year they worked at Oracle (again, if any).
"For each member_id" translates to GROUP BY member_id
"Get the first year..." translates to MIN( CASE WHEN "Company" = 'etc' THEN "Year_Started" END )
Filter those rows to rows where the first-year-at-IBM is less-than their first-year-at-Oracle.
Then simply get the COUNT(*) of those rows.
WITH ibmOracleYears AS (
SELECT
member_id,
MIN( CASE WHEN "Company" = 'IBM' THEN "Year_Started" END ) AS JoinedIbm,
MIN( CASE WHEN "Company" = 'Oracle' THEN "Year_Started" END ) AS JoinedOracle
FROM
yourTable
GROUP BY
member_id
),
workedAtIbmBeforeOracle AS (
SELECT
y.*
FROM
ibmOracleYears AS y
WHERE
y.JoinedIbm IS NOT NULL /* <-- This `IS NOT NULL` check isn't absolutely necessary, but I'm including it for clarity. */
AND
y.JoinedOracle IS NOT NULL
AND
y.JoinedIbm < y.JoinedOracle
)
SELECT
COUNT(*) AS "Number of members that worked at IBM before Oracle"
FROM
workedAtIbmBeforeOracle
But that query can be reduced down to this (if you don't mind anonymous expressions in HAVING clauses):
SELECT
COUNT(*) AS "Number of members that worked at IBM before Oracle"
FROM
(
SELECT
member_id
FROM
yourTable
GROUP BY
member_id
HAVING
MIN( CASE WHEN "Company" = 'IBM' THEN "Year_Started" END ) < MIN( CASE WHEN "Company" = 'Oracle' THEN "Year_Started" END )
) AS q
SQLFiddle of both examples.

The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have a query and i want to order by CreatationDateTime form requestFolders
But I get this error.
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
my query is :
with requests as (
select IRF.Id as Id,
P.Id as ProcessId,
N'Investment' as [ServiceType],
IRF.FolderNumber as FolderNumber,
P.[Name] as [TypeTitle],
S.CustomerDisplayInfo_CustomerTitle as [CurrentStatus],
S.CustomerDisplayInfo_CustomerOrder as [CurrentStatusOrder],
RH.OccuredDateTime as [CurrentStatusDate],
IRF.CreationDateTime as [RequestDate],
IRF.RequestedAmount as [Amount],
(case when A.Id is not Null and s.sidetype='CustomerSide' then 1 else 0 end) as [HasAction],
rank() over ( partition by IRF.Id order by rh.OccuredDateTime desc) as rnk
from
[Investment].[dbo].[InvestmentRequestFolders] as IRF inner join
[Investment].[dbo].[RequestHistories] as RH on IRF.Id = RH.ObjectId inner join
[Investment].[dbo].[Processes] as P on P.Id = RH.ProcessId inner join
[Investment].[dbo].[Step] as S on S.Id = RH.ToStep left join
[Investment].[dbo].[Actions] as A on A.StepId = RH.ToStep
where IRF.Applicant_ApplicantId = '89669CD7-9914-4B3D-AFEA-61E3021EEC30'
-- the error is here
order by IRF.CreationDateTime
) SELECT t.Id,
max(t.ProcessId) as [ProcessId],
t.[ServiceType] as [ServiceType],
isnull(max(t.TypeTitle), '-') as [TypeTitle],
isnull(max(t.FolderNumber), '-') as [RequestNumber],
isnull(max(t.CurrentStatus), '-') as [CurrentStatus],
isnull(max(t.CurrentStatusOrder), '-') as [CurrentStatusOrder],
max(t.CurrentStatusDate)as [CurrentStatusDate],
max(t.RequestDate) as [RequestDate],
max(t.HasAction) as [HasAction],
isnull(max(t.Amount), 0) as [Amount]
FROM requests as t
where t.rnk = 1
GROUP BY t.Id
The error is on Msg 1033, Level 15, State 1, Line 24
Please help me.
In almost all cases, you can simply drop the CTE's ORDER BY clause. Even if it were permitted syntactically (it is in other RDBMS), it has no effect on your query's result the way you wrote it.
Now, if for some reason, you absolutely have to keep it there, you can add a TOP clause, e.g. one without any effect such as TOP 100 PERCENT, i.e.:
with requests as (
select top 100 percent
IRF.Id as Id,
...
A full, simplified example:
-- Doesn't work
with t (a) as (
select a
from (values (1),(3),(2)) t (a)
order by a
)
select a from t order by a
-- Works
with t (a) as (
select top 100 percent a
from (values (1),(3),(2)) t (a)
order by a
)
select a from t order by a

Percentage calculation always returns me 0 even that the values are numbers [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I'm trying to create a percentage for some errors in my table.
I build a query that brings the qty of errors per each value, the total errors, and the division.
But is always giving me 0 (I added a check in order to see if the values are numeric) .
select
ZZ0010 as Error_type
, qty
, total
,running_sum
, isnumeric(total)
,isnumeric(running_sum)
,running_sum/total
from (
select ZZ0010
,(count( [ZZ0010] )) as qty
,sum(nullif(count( [ZZ0010] ),0) ) over(order by count( [ZZ0010] ) desc,ZZ0010) as running_sum
,sum(nullif(count( [ZZ0010] ),0) ) over() as total
from md.CAR_CRM_DS_ZCRM_Z101_BUSINESS_ATTR_VT
group by ZZ0010
having (count( [ZZ0010] )) is not null
) tbl
order by running_sum asc
Error_type
qty
total
running_sum
isnumeric(total)
isnumeric(running_sum)
running_sum/total
2
2123
3931
2123
1
1
0
10
1808
3931
3931
1
1
0
Hmmm . . . I think you can radically simplify this:
select ZZ0010,
count(*) as qty,
sum(count(*)) over (order by count(*) desc) as running_sum,
sum(count(*)) over () as total,
( sum(count(*)) over (order by count(*) desc) * 1.0 /
nullif(sum(count(*)) over (), 0)
) as ratio
from md.CAR_CRM_DS_ZCRM_Z101_BUSINESS_ATTR_VT
group by ZZ0010;
Notes:
I don't know why you would use isnumeric() on number columns.
COUNT() cannot return NULL so the HAVING is redundant.
Use NULLIF() to avoid division by 0. Of course, the sum of counts cannot be zero in your query unless all rows have ZZ0010 as NULL.
SQL Server does integer division. I just multiply by 1.0 to avoid this.
NULLIF(COUNT(), 0) is just really strange. Why distinguish between 0 and NULL in a column that ignores nulls?
I don't think a subquery is particularly useful in this case, but if you don't want to repeat the expressions, you can certainly use a subquery.

Skip rows for specific time in SQL

Need a help.
I have two timestamp columns, so basically I want to get the max and min value with a thirD column showing as timedifference. I am skipping any 12.am time so used the syntax below. ANy help how to achieve the third column, timedifference.. It is in DB2.
SELECT EMPID,MIN(STARTDATETIME),MAX(ENDDATETIME)
FROM TABLE
WHERE DATE(STARTDATETIME)= '2012-05-15' AND HOUR(STARTDATETIME)<>0 AND HOUR(ENDDATETIME)<>0
GROUP BY EMPID
You can use the results from that in an inner select, and use those values to define the TimeDifference column. My knowledge of DB2 is very limited, so I'm making some assumptions, but this should give you an idea. I'll update the answer if something is drastically incorrect.
Select EmpId,
MinStartDate,
MaxEndDate,
MaxEndDate - MinStartDate As TimeDifference
From
(
Select EMPID,
MIN(STARTDATETIME) As MinStartDate,
MAX(ENDDATETIME) As MaxEndDate
From Table
Where DATE(STARTDATETIME) = '2012-05-15'
And HOUR(STARTDATETIME) <> 0
And HOUR(ENDDATETIME) <> 0
Group By EMPID
) A

TSQL- Rollup SQL 2005

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