I'm trying to add an aggregate sub query in select statement for the following code.
DECLARE #Date1 Date
DECLARE #Date2 Date
SET #Date1 = '2017-01-01'
SET #Date2 = '2017-03-01'
SELECT
p.PracticeName [Practice Name],
dbo.getFormattedName(l.Userid) [User Name],
MAX(EventDate) [Last Activity],
COUNT(*) [Activity Count],
(SELECT COUNT(*)
FROM UserEvent EVT (NOLOCK)
WHERE EVT.EventTypeID = 1
AND EVT.UserID = au.userID
AND EVT.EventDate >= #Date1
AND EVT.EventDate <= DATEADD(DAY, 1, #Date2)
GROUP BY
au.userID) [Login Count]
FROM
dbo.AudLog l (NOLOCK)
JOIN
Appuser au (NOLOCK) ON l.UserID = au.UserID
JOIN
Practice p (NOLOCK) ON au.PracticeID = p.PracticeID
WHERE
l.EnvironmentID = 1
AND EventDate >= #Date1
AND EventDate <= DATEADD(DAY,1,#Date2)
GROUP BY
p.PracticeName,
dbo.getFormattedName(l.Userid)
ORDER BY
p.PracticeName,
dbo.getFormattedName(l.Userid)
I'm getting the following error:
Column 'Appuser.UserID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I don't understand why that error applies to my sub query because I'm not selecting AppUser.UserID, I'm just using as a reference for a condition to align the sub query with the parent query. Also, it is indeed in the GROUP BY statement within the sub query.
I referenced this question but based on the explanation I would think my query would be working.
Any help appreciated.
The question you are referencing is different because there are no aggregate functions in the outer query that require a GROUP BY.
When you use a correlated subquery as your have (EVT.UserID = au.userID), the outer query column reference, in this case au.userID, is now a part of the columns in the outer select (because it is necessary to the subquery).
The simple fix is to add the au.userID column to your outer group by.
If you join on a field it is present in the intermediary data set that is part of the join. Even if it is not in your select list you need to consider it as part of the list.
If you really think it is a non-issue then you can add it to your group by clause and still get the results you desire.
The error is not referencing your sub query.
The following line dbo.ch_getFormattedProviderName(l.Userid) in the select clause of your main query is the problem.
You are using the function call dbo.ch_getFormattedProviderName(l.Userid) in your select statement but you are grouping by a different function dbo.getFormattedName(l.Userid) in your group by clause.
Change the function dbo.ch_getFormattedProviderName to dbo.getFormattedName or vice versa.
It is not answer to your question, but. There are some several things I would like to mention in your query.
Avoid using scalar functions. Try not use them at all. They are almost no good examples of usage of them. If you wish to encapsulate the logic then just use Table Valued Functions instead. Scalar functions are performance killers especially if you need to filter by them. They will not be indexed and they will execute on every single row.
Personally I didn't see the situation when such inline sub-queries would outperform normal JOIN inline query. But I saw a lot of opposite situations when the performance was worse. You can always re-write such query with the JOIN (SELECT ...)
NOLOCKs ... they are not very recommended. If you have locking problems then solving them by taking using index/re-design Technics. It is better to solve the root of the problem rather than doing workarounds.
Related
I run the following query:
SELECT
orderdetails.sku,
orderdetails.mf_item_number,
orderdetails.qty,
orderdetails.price,
supplier.supplierid,
supplier.suppliername,
supplier.dropshipfees,
cost = (SELECT supplier_item.price
FROM supplier_item,
orderdetails,
supplier
WHERE supplier_item.sku = orderdetails.sku
AND supplier_item.supplierid = supplier.supplierid)
FROM orderdetails,
supplier,
group_master
WHERE invoiceid = '339740'
AND orderdetails.mfr_id = supplier.supplierid
AND group_master.sku = orderdetails.sku
I get the following error:
Msg 512, Level 16, State 1, Line 2
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Any ideas?
Try this:
SELECT
od.Sku,
od.mf_item_number,
od.Qty,
od.Price,
s.SupplierId,
s.SupplierName,
s.DropShipFees,
si.Price as cost
FROM
OrderDetails od
INNER JOIN Supplier s on s.SupplierId = od.Mfr_ID
INNER JOIN Group_Master gm on gm.Sku = od.Sku
INNER JOIN Supplier_Item si on si.SKU = od.Sku and si.SupplierId = s.SupplierID
WHERE
od.invoiceid = '339740'
This will return multiple rows that are identical except for the cost column. Look at the different cost values that are returned and figure out what is causing the different values. Then ask somebody which cost value they want, and add the criteria to the query that will select that cost.
Check to see if there are any triggers on the table you are trying to execute queries against. They can sometimes throw this error as they are trying to run the update/select/insert trigger that is on the table.
You can modify your query to disable then enable the trigger if the trigger DOES NOT need to be executed for whatever query you are trying to run.
ALTER TABLE your_table DISABLE TRIGGER [the_trigger_name]
UPDATE your_table
SET Gender = 'Female'
WHERE (Gender = 'Male')
ALTER TABLE your_table ENABLE TRIGGER [the_trigger_name]
SELECT COLUMN
FROM TABLE
WHERE columns_name
IN ( SELECT COLUMN FROM TABLE WHERE columns_name = 'value');
note: when we are using sub-query we must focus on these points:
if our sub query returns 1 value in this case we need to use (=,!=,<>,<,>....)
else (more than one value), in this case we need to use (in, any, all, some )
cost = Select Supplier_Item.Price from Supplier_Item,orderdetails,Supplier
where Supplier_Item.SKU=OrderDetails.Sku and
Supplier_Item.SupplierId=Supplier.SupplierID
This subquery returns multiple values, SQL is complaining because it can't assign multiple values to cost in a single record.
Some ideas:
Fix the data such that the existing subquery returns only 1 record
Fix the subquery such that it only returns one record
Add a top 1 and order by to the subquery (nasty solution that DBAs hate - but it "works")
Use a user defined function to concatenate the results of the subquery into a single string
The fix is to stop using correlated subqueries and use joins instead. Correlated subqueries are essentially cursors as they cause the query to run row-by-row and should be avoided.
You may need a derived table in the join in order to get the value you want in the field if you want only one record to match, if you need both values then the ordinary join will do that but you will get multiple records for the same id in the results set. If you only want one, you need to decide which one and do that in the code, you could use a top 1 with an order by, you could use max(), you could use min(), etc, depending on what your real requirement for the data is.
I had the same problem , I used in instead of = , from the Northwind database example :
Query is : Find the Companies that placed orders in 1997
Try this :
SELECT CompanyName
FROM Customers
WHERE CustomerID IN (
SELECT CustomerID
FROM Orders
WHERE YEAR(OrderDate) = '1997'
);
Instead of that :
SELECT CompanyName
FROM Customers
WHERE CustomerID =
(
SELECT CustomerID
FROM Orders
WHERE YEAR(OrderDate) = '1997'
);
Either your data is bad, or it's not structured the way you think it is. Possibly both.
To prove/disprove this hypothesis, run this query:
SELECT * from
(
SELECT count(*) as c, Supplier_Item.SKU
FROM Supplier_Item
INNER JOIN orderdetails
ON Supplier_Item.sku = orderdetails.sku
INNER JOIN Supplier
ON Supplier_item.supplierID = Supplier.SupplierID
GROUP BY Supplier_Item.SKU
) x
WHERE c > 1
ORDER BY c DESC
If this returns just a few rows, then your data is bad. If it returns lots of rows, then your data is not structured the way you think it is. (If it returns zero rows, I'm wrong.)
I'm guessing that you have orders containing the same SKU multiple times (two separate line items, both ordering the same SKU).
The select statement in the cost part of your select is returning more than one value. You need to add more where clauses, or use an aggregation.
The error implies that this subquery is returning more than 1 row:
(Select Supplier_Item.Price from Supplier_Item,orderdetails,Supplier where Supplier_Item.SKU=OrderDetails.Sku and Supplier_Item.SupplierId=Supplier.SupplierID )
You probably don't want to include the orderdetails and supplier tables in the subquery, because you want to reference the values selected from those tables in the outer query. So I think you want the subquery to be simply:
(Select Supplier_Item.Price from Supplier_Item where Supplier_Item.SKU=OrderDetails.Sku and Supplier_Item.SupplierId=Supplier.SupplierID )
I suggest you read up on correlated vs. non-correlated subqueries.
As others have suggested, the best way to do this is to use a join instead of variable assignment. Re-writing your query to use a join (and using the explicit join syntax instead of the implicit join, which was also suggested--and is the best practice), you would get something like this:
select
OrderDetails.Sku,
OrderDetails.mf_item_number,
OrderDetails.Qty,
OrderDetails.Price,
Supplier.SupplierId,
Supplier.SupplierName,
Supplier.DropShipFees,
Supplier_Item.Price as cost
from
OrderDetails
join Supplier on OrderDetails.Mfr_ID = Supplier.SupplierId
join Group_Master on Group_Master.Sku = OrderDetails.Sku
join Supplier_Item on
Supplier_Item.SKU=OrderDetails.Sku and Supplier_Item.SupplierId=Supplier.SupplierID
where
invoiceid='339740'
Even after 9 years of the original post, this helped me.
If you are receiving these types of errors without any clue, there should be a trigger, function related to the table, and obviously it should end up with an SP, or function with selecting/filtering data NOT USING Primary Unique column. If you are searching/filtering using the Primary Unique column there won't be any multiple results. Especially when you are assigning value for a declared variable. The SP never gives you en error but only an runtime error.
"System.Data.SqlClient.SqlException (0x80131904): Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated."
In my case obviously there was no clue, but only this error message. There was a trigger connected to the table and the table updating by the trigger also had another trigger likewise it ended up with two triggers and in the end with an SP. The SP was having a select clause which was resulting in multiple rows.
SET #Variable1 =(
SELECT column_gonna_asign
FROM dbo.your_db
WHERE Non_primary_non_unique_key= #Variable2
If this returns multiple rows, you are in trouble.
I need some help in writing a SQL Server stored procedure. All data group by Train_B_N.
my table data
Expected result :
expecting output
with CTE as
(
select Train_B_N, Duration,Date,Trainer,Train_code,Training_Program
from Train_M
group by Train_B_N
)
select
*
from Train_M as m
join CTE as c on c.Train_B_N = m.Train_B_N
whats wrong with my query?
The GROUP BY smashes the table together, so having columns that are not GROUPED combine would cause problems with the data.
select Train_B_N, Duration,Date,Trainer,Train_code,Training_Program
from Train_M
group by Train_B_N
By ANSI standard, the GROUP BY must include all columns that are in the SELECT statement which are not in an aggregate function. No exceptions.
WITH CTE AS (SELECT TRAIN_B_N, MAX(DATE) AS Last_Date
FROM TRAIN_M
GROUP BY TRAIN_B_N)
SELECT A.Train_B_N, Duration, Date,Trainer,Train_code,Training_Program
FROM TRAIN_M AS A
INNER JOIN CTE ON CTE.Train_B_N = A.Train_B_N
AND CTE.Last_Date = A.Date
This example would return the last training program, trainer, train_code used by that ID.
This is accomplished from MAX(DATE) aggregate function, which kept the greatest (latest) DATE in the table. And since the GROUP BY smashed the rows to their distinct groupings, the JOIN only returns a subset of the table's results.
Keep in mind that SQL will return #table_rows X #Matching_rows, and if your #Matching_rows cardinality is greater than one, you will get extra rows.
Look up GROUP BY - MSDN. I suggest you read everything outside the syntax examples initially and obsorb what the purpose of the clause is.
Also, next time, try googling your problem like this: 'GROUP BY, SQL' or insert the error code given by your IDE (SSMS or otherwise). You need to understand why things work...and SO is here to help, not be your google search engine. ;)
Hope you find this begins your interest in learning all about SQL. :D
I have this below query
SELECT A.*,SUM(ISNULL(B.DEPTRAN_DEPOSIT,0)-ISNULL(B.DEPTRAN_WITHDRAWAL,0)) as BALANCE
FROM DEPOSITFDMASTER A
INNER JOIN DEPOSITTRANSACTION B ON A.DEPSUBTYPE_ID=B.DEPSUBTYPE_ID AND A.FD_ID=B.DEPOSIT_DATAID WHERE SUM(ISNULL(B.DEPTRAN_DEPOSIT,0)-ISNULL(B.DEPTRAN_WITHDRAWAL,0))>10
when i try to execute i will get the below error. If i remove where condtion then the query will work properly.
An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list, and the column being aggregated is an outer reference.
P.S:DEPTRAN_DEPOSIT and DEPTRAN_WITHDRAWAL both having DataType Decimal(18,2).
Any help appreciated.
I'd suggest you use GROUP BY and HAVING. Something like this
SELECT
A.*
,SUM(ISNULL(B.DEPTRAN_DEPOSIT,0)-ISNULL(B.DEPTRAN_WITHDRAWAL,0)) as BALANCE
FROM DEPOSITFDMASTER A
INNER JOIN DEPOSITTRANSACTION B
ON
A.DEPSUBTYPE_ID=B.DEPSUBTYPE_ID
AND
A.FD_ID=B.DEPOSIT_DATAID
GROUP BY [All columns in A] --like that A.Column1,A.COlumn2,....,A.ColumnN
HAVING SUM(ISNULL(B.DEPTRAN_DEPOSIT,0)-ISNULL(B.DEPTRAN_WITHDRAWAL,0))>10
I've seen similar errors on SO, but I don't find a solution for my problem.
I have a SQL query like:
SELECT DISTINCT
a.maxa ,
b.mahuyen ,
a.tenxa ,
b.tenhuyen ,
ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa a ,
quanhuyen b
LEFT OUTER JOIN ( SELECT maxa ,
COUNT(*) AS tong
FROM khaosat
WHERE CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
AND
'Sep 5 2011'
GROUP BY maxa
) AS dkcd ON dkcd.maxa = a.maxa
WHERE a.maxa <> '99'
AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;
When I execute this query, the error result is:
The multi-part identifier "a.maxa" could not be bound. Why?
P/s: if i divide the query into 2 individual query, it run ok.
SELECT DISTINCT
a.maxa ,
b.mahuyen ,
a.tenxa ,
b.tenhuyen
FROM phuongxa a ,
quanhuyen b
WHERE a.maxa <> '99'
AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;
and
SELECT maxa ,
COUNT(*) AS tong
FROM khaosat
WHERE CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
AND 'Sep 5 2011'
GROUP BY maxa;
You are mixing implicit joins with explicit joins. That is allowed, but you need to be aware of how to do that properly.
The thing is, explicit joins (the ones that are implemented using the JOIN keyword) take precedence over implicit ones (the 'comma' joins, where the join condition is specified in the WHERE clause).
Here's an outline of your query:
SELECT
…
FROM a, b LEFT JOIN dkcd ON …
WHERE …
You are probably expecting it to behave like this:
SELECT
…
FROM (a, b) LEFT JOIN dkcd ON …
WHERE …
that is, the combination of tables a and b is joined with the table dkcd. In fact, what's happening is
SELECT
…
FROM a, (b LEFT JOIN dkcd ON …)
WHERE …
that is, as you may already have understood, dkcd is joined specifically against b and only b, then the result of the join is combined with a and filtered further with the WHERE clause. In this case, any reference to a in the ON clause is invalid, a is unknown at that point. That is why you are getting the error message.
If I were you, I would probably try to rewrite this query, and one possible solution might be:
SELECT DISTINCT
a.maxa,
b.mahuyen,
a.tenxa,
b.tenhuyen,
ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa a
INNER JOIN quanhuyen b ON LEFT(a.maxa, 2) = b.mahuyen
LEFT OUTER JOIN (
SELECT
maxa,
COUNT(*) AS tong
FROM khaosat
WHERE CONVERT(datetime, ngaylap, 103) BETWEEN 'Sep 1 2011' AND 'Sep 5 2011'
GROUP BY maxa
) AS dkcd ON dkcd.maxa = a.maxa
WHERE a.maxa <> '99'
ORDER BY a.maxa
Here the tables a and b are joined first, then the result is joined to dkcd. Basically, this is the same query as yours, only using a different syntax for one of the joins, which makes a great difference: the reference a.maxa in the dkcd's join condition is now absolutely valid.
As #Aaron Bertrand has correctly noted, you should probably qualify maxa with a specific alias, probably a, in the ORDER BY clause.
Sometimes this error occurs when you use your schema (dbo) in your query in a wrong way.
for example if you write:
select dbo.prd.name
from dbo.product prd
you will get the error.
In this situations change it to:
select prd.name
from dbo.product prd
if you have given alies name change that to actual name
for example
SELECT
A.name,A.date
FROM [LoginInfo].[dbo].[TableA] as A
join
[LoginInfo].[dbo].[TableA] as B
on [LoginInfo].[dbo].[TableA].name=[LoginInfo].[dbo].[TableB].name;
change that to
SELECT
A.name,A.date
FROM [LoginInfo].[dbo].[TableA] as A
join
[LoginInfo].[dbo].[TableA] as B
on A.name=B.name;
I was struggling with the same error message in SQL SERVER, since I had multiple joins, changing the order of the joins solved it for me.
In my case the issue turned out to be the alias name I had given to the table. "oa" seems to be not acceptable for SQL Server.
What worked for me was to change my WHERE clause into a SELECT subquery
FROM:
DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = [dbo].FetchedTagTransferData.IssueId
TO:
DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = (SELECT NoteId FROM FetchedTagTransferData)
I was having the same error from JDBC. Checked everything and my query was fine. Turned out, in where clause I have an argument:
where s.some_column = ?
And the value of the argument I was passing in was null. This also gives the same error which is misleading because when you search the internet you end up that something is wrong with the query structure but it's not in my case. Just thought someone may face the same issue
I'm new to SQL, but came across this issue in a course I was taking and found that assigning the query to the project specifically helped to eliminate the multi-part error. For example the project I created was CTU SQL Project so I made sure I started my script with USE [CTU SQL Project] as my first line like below.
USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.
If this error happens in an UPDATE, double-check the JOIN on the table with the column/field that is causing the error.
In my case this was due to the lack of the JOIN itself, which generated the same error due to an unknown field (as Andriy pointed out).
Instead you can try joining tables like,
select
....
from
dkcd
right join
a
, b
This should work
SELECT DISTINCT
phuongxa.maxa ,
quanhuyen.mahuyen ,
phuongxa.tenxa ,
quanhuyen.tenhuyen ,
ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa ,
quanhuyen
LEFT OUTER JOIN ( SELECT khaosat.maxa ,
COUNT(*) AS tong
FROM khaosat
WHERE CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
AND
'Sep 5 2011'
GROUP BY khaosat.maxa
) AS dkcd ON dkcd.maxa = maxa
WHERE phuongxa.maxa <> '99'
AND LEFT(phuongxa.maxa, 2) = quanhuyen.mahuyen
ORDER BY maxa;
My error was to use a field that did not exist in table.
table1.field1 => is not exist
table2.field1 => is correct
Correct your Table Name.
my error occurred because of using WITH
WITH RCTE AS (
SELECT...
)
SELECT RCTE.Name, ...
FROM
RCTE INNER JOIN Customer
ON RCTE.CustomerID = Customer.ID
when used in join with other tables ...
Did you forget to join some tables? If not then you probably need to use some aliases.
I was also struggling with this error and ended up with the same strategy as the answer. I am including my answer just to confirm that this is a strategy that should work.
Here is an example where I do first one inner join between two tables I know got data and then two left outer joins on tables that might have corresponding rows that can be empty. You mix inner joins and outer joins to get results with data accross tables instead of doing the default comma separated syntax between tables and miss out rows in your desired join.
use somedatabase
go
select o.operationid, o.operatingdate, p.pasid, p.name as patientname, o.operationalunitid, f.name as operasjonsprogram, o.theaterid as stueid, t.name as stuenavn, o.status as operasjonsstatus from operation o
inner join patient p on o.operationid = p.operationid
left outer join freshorganizationalunit f on f.freshorganizationalunitid = o.operationalunitid
left outer join theater t on t.theaterid = o.theaterid
where (p.Name like '%Male[0-9]%' or p.Name like '%KFemale [0-9]%')
First: Do the inner joins between tables you expect to have data matching.
Second part: Continue with outer joins to try to retrieve data in other tables,
but this will not filter out your result set if table outer joining to has not got corresponding data or match on the condition you set up in the on predicate / condition.
This error can also be caused by simply missing a comma , between the column names in the SELECT statement.
eg:
SELECT MyCol1, MyCol2 MyCol3 FROM SomeTable;
For me the issue was that I was stupidly calling a DB function without empty brackets select [apo].[GenerateNationalIdFrance] instead of select [apo].[GenerateNationalIdFrance]() ... took me few minutes to realize that but worth mentioning for juniors out there :-)
For me I was using wrong alias spellings , it worked after correct spelings
I have a SQL Server query which runs just fine -- until I add a computed column to the SELECT statement. Then I get an odd SQL Server error.
Here's the SQL:
SELECT
outmail_.MessageID_,
CONVERT(VARCHAR(10),outmail_.Created_,120) AS 'Issue',
lyrReportSummaryData.mailed,
lyrReportSummaryData.successes,
COUNT(*) AS 'opens',
COUNT(DISTINCT clicktracking_.MemberID_) AS 'unique_opens',
convert(decimal(3,1),((convert(float,[unique_opens]))/[successes]) * 100) AS 'Rate'
FROM
outmail_
RIGHT JOIN
clicktracking_ ON clicktracking_.MessageID_ = outmail_.MessageID_
RIGHT JOIN
lyrReportSummaryData ON lyrReportSummaryData.id = clicktracking_.MessageID_
GROUP BY
outmail_.MessageID_, CONVERT(VARCHAR(10), outmail_.Created_,120),
lyrReportSummaryData.mailed, lyrReportSummaryData.successes
The problem is the line beginning with the convert(decimal ... When it is included, I get the following error:
Error 8120: Column 'lyrReportSummaryData.unique_opens' is invalid in
the select list because it is not contained in either an aggregate
function or the GROUP BY clause.
I'm not sure how to resolve the error since I don't know how to use it in a GROUP BY clause (and it doesn't seem that I should need to do so).
Any suggestions for how to proceed? Thanks.
I'm sure someone with better DBA skills than me can point out a more efficient way of doing this, but...
If you perform the bulk of your query as an sub-query, you can then do the calculations on the result of your sub-query:
SELECT
MessageID_,
Issue,
mailed,
successes,
opens,
unique_opens,
convert(decimal(3,1),((convert(float,[unique_opens]))/[successes]) * 100) AS 'Rate'
FROM
(SELECT
outmail_.MessageID_,
CONVERT(VARCHAR(10),outmail_.Created_,120) AS 'Issue',
lyrReportSummaryData.mailed,
lyrReportSummaryData.successes,
COUNT(*) AS 'opens',
COUNT(DISTINCT clicktracking_.MemberID_) AS 'unique_opens'
FROM outmail_
RIGHT JOIN clicktracking_ ON clicktracking_.MessageID_ = outmail_.MessageID_
RIGHT JOIN lyrReportSummaryData ON lyrReportSummaryData.id = clicktracking_.MessageID_
GROUP BY outmail_.MessageID_, CONVERT(VARCHAR(10), outmail_.Created_,120), lyrReportSummaryData.mailed, lyrReportSummaryData.successes
) subquery /* was 'g' */
Effectively what this does is runs the grouping, and then based on that, does the calculation afterwards.
Subqueries must be given an alias (in this instance 'subquery') - even if you don't use that alias name.