An error : Subquery returned more than 1 value - sql

I am getting the error-msg when i try the following code:
SELECT COUNT(*) FROM [ServerName].[dbo].[TableName1] B
WHERE right(B.TableName1, 2) = '34' AND
B.UnitId=
(select distinct D.UnitId
from [ServerName].[dbo].[TableName2] D
INNER JOIN #temp E ON D.UnitId=E.UnitId)
Does anyone know how to solve it? It says the subquery returned more than 1 value. The temp-table is created and contains a selection of the number individuals that I want to count, by unitId.

Try using a join instead of the subquery:
SELECT COUNT(*)
FROM [ServerName].[dbo].[TableName1] B
INNER JOIN [ServerName].[dbo].[TableName2] D ON B.UnitId = D.UnitId
INNER JOIN #temp E ON D.UnitId = E.UnitId
WHERE RIGHT(B.TableName1, 2) = '34'

The subquery (select distinct) has more than one value returned. As such B.UnitId cannot equal more than one value.
You can use IN if its ok for B.UnitId to have more than one value.
SELECT COUNT(*)
FROM [ServerName].[dbo].[TableName1] B
WHERE right(B.TableName1, 2) = '34'
AND B.UnitId in (select D.UnitId
from [ServerName].[dbo].[TableName2] D
INNER JOIN #temp E ON D.UnitId=E.UnitId)
Distinct becomes superfluous when you use IN.

Related

Subquery problem when using WHERE in secondary SELECT

I have problem with query.
SELECT
a.code,
b.codename,
(SELECT COUNT(b.IdNum)
FROM
(SELECT *
FROM NumTable
WHERE YEAR(DateOfPoint) = 2019)) AS CountNumber
FROM
NumTable b
JOIN
CodeTable a ON a.id = b.id
WHERE
a.SellYear IS NOT NULL
My First question is about CountNumber is it ok ? I need to count only those b.IdNum that have DateOfPoint = 2019. It should only be to this field not to any other in this query, thats why I didn't use it in the end in WHERE.
Second question is about CountNumber too becouse I still get error msg that I got there incorrect syntax I was looking for it for about hour and couldn't find it.
Thanks
not sure what you are trying to get here but I think group by is more logicly here
SELECT a.code
,b.codename
,Sum(case when b.DateOfPoint= 2019 then 1 else 0) as CountNumber
FROM NumTable b
JOIN CodeTable a ON a.id = b.id
WHERE a.SellYear IS NOT NULL
group by a.code,b.codename
you will get a row for each code and codename and the number of dateofPoint in 2019 that it have if there are none it will return 0
You can use this query. I think, it will work for you:
SELECT a.code,
b.codename
FROM
NumTable b
JOIN
CodeTable a ON a.id = b.id
JOIN
(SELECT *
FROM NumTable
WHERE YEAR(DateOfPoint) = 2019) c ON c.id = b.id
JOIN
(SELECT id, COUNT(b.IdNum) FROM c) d ON c.id = d.id
WHERE
a.SellYear IS NOT NULL
You can use a window function:
SELECT c.code, n.codename, c.cnt_2019
FROM (SELECT n.*,
SUM(CASE WHEN YEAR(DateOfPoint) = 2019 THEN 1 ELSE 0 END) as cnt_2019
FROM NumTable n
) n JOIN
CodeTable c
ON c.id = n.id
WHERE c.SellYear IS NOT NULL;
Note that I also changed the table aliases so they are abbreviations for the table names rather than arbitrary letters.

Count with exists in SQL

Why is this query not returning the count of the results? How do I get it to show the count
SELECT COUNT (*) AS MWith
FROM member m
JOIN Channel mc ON mc.MemberID = m.id
JOIN Client c ON c.id = m.clientid
JOIN packages p ON p.id = m.packageid
WHERE Enroll > '2018'
AND EXISTS (
SELECT * FROM
activity a
WHERE a.memberid = m.id
AND a.code IN ('785', 'a599')
)
GROUP BY m.id;
OUTPUT
MWith
1
1
1
The empty set is because of the clause group by .
The workarounds are:
Remove a GROUP BY, because m.id anyway is not part of the output
Use GROUP BY ALL
An original example:
SELECT COUNT(*) AS MWith
FROM member m
JOIN Channel mc
ON mc.MemberID = m.id
JOIN Client c
ON c.id = m.clientid
JOIN packages p
ON p.id = m.packageid
WHERE Enroll > '2018'
AND EXISTS
(
SELECT *
FROM activity a
WHERE a.memberid = m.id
AND a.code IN ( '785', 'a599' )
)
-- GROUP BY m.id;
Other, simpler examples to show a difference:
-- returns an empty resultset
SELECT COUNT(*) FROM sys.databases
WHERE 1=0
GROUP BY name
-- returns: a single row with 0
SELECT COUNT(*) FROM sys.databases
WHERE 1=0
-- Another example with GROUP BY ALL
-- it returns one row per grouped value, with expected count = 0
SELECT COUNT(*) FROM sys.databases
WHERE 1=0
GROUP BY ALL name

Count with row_number function SQL CTE

I have the below CTEs that work perfectly, but I want to count the "cl.memb_dim_id" by "cl.post_date" but I am not sure how to do that? When adding in the count function I get an error that highlights the ' row number' so I am assuming I cant have both order and group together ????
WITH
DATES AS
(
select to_date('01-jan-2017') as startdate,to_date('02-jan-2017') as enddate
from dual
),
Claims as (select distinct
cl.memb_dim_id,
row_number () over (partition by cl.Claim_number order by cl.post_date desc) as uniquerow,
cl.Claim_number,
cl.post_date,
ct.claim_type,
ap.claim_status_desc,
dc.company_desc,
dff.io_flag_desc,
pr.product_desc,
cl.prov_dim_id,
cl.prov_type_dim_id
from dw.fact_claim cl
inner join dates d
on 1=1
and cl.post_date >= d.startdate
and cl.post_date <= d.enddate
and cl.provider_par_dim_id in ('2')
and cl.processing_status_dim_id = '1'
and cl.company_dim_id in ('581','585','586','589','590','591','588','592','594','601','602','603','606','596','598','597','579','599','578','577','573','574','576','575')
left join dw.DIM_CLAIM_STATUS ap
on cl.claim_status_dim_id = ap.claim_status_dim_id
left join dw.dim_claim_type ct
on cl.claim_type_dim_id = ct.claim_type_dim_id
and cl.claim_type_dim_id in ('1','2','6','7')
left join dw.DIM_COMPANY dc
on cl.company_dim_id = dc.company_dim_id
left join dw.DIM_IO_FLAG dff
on cl.io_flag_dim_id = dff.io_flag_dim_id
left join dw.dim_product pr
on cl.product_dim_id = pr.product_dim_id
)
Select * from claims where uniquerow ='1'
First, does this work?
count(cl.memb_dim_id) over (partition by cl.Claim_number, cl.post_date) as cnt,
Second, it is strange to be using analytic functions with select distinct.

Select only the rows where column values appear more than once

I have a select statement similar to the following:
select *
from A
inner join B on A.id_x = B.id_x
inner join C on B.id_y = C.id_y
inner join D on C.id_z = D.id_z
where
A.date > '2014-01-01'
and A.id_y = 154
and D.id_t = 2
What I want is to do something like this and count(A.id_x) > 1, which returns only the parts of the original select which repeat on A.id_x.
Is this possible?
EDIT:
I just tried to solve it using temp tables, with the code I got from T-SQL Insert into table without having to specify every column
Select * Into
#tmpBigTable
From [YourBigTable]
But I got an error message because my tables have the same column names, A.id_x and B.id_x, for example.
"Column names in each table must be unique."
Is there some way to force the issue, or declare arbitrary naming extensions?
select *
from A
inner join B on A.id_x = B.id_x
inner join C on B.id_y = C.id_y
inner join D on C.id_z = D.id_z
where
A.date > '2014-01-01'
and A.id_y = 154
and D.id_t = 2
AND A.id_x IN
(
SELECT A.id_x FROM A
GROUP BY A.id_x
HAVING count(A.id_x)>1);
You can do this with window functions:
select *
from (select *, count(*) over (partition by A.id_x) as cnt
from A inner join
B
on A.id_x = B.id_x inner join
C
on B.id_y = C.id_y inner join
D
on C.id_z = D.id_z
where A.date > '2014-01-01' and A.id_y = 154 and D.id_t = 2
) abcd
where cnt > 1;

selecting the max values based on a count

How can i retrieve the max of each ValueCount based on the firmid. I need the data to be output like so.
My code is below
SELECT
F.FirmID,
F.Name,
DL.ValueId,
DL.ValueName,
count(DL.ValueName) AS ValueCount
FROM
dbo.Jobs AS J
INNER JOIN DimensionValues AS DV ON
DV.CrossRef = J.JobId
INNER JOIN dbo.DimensionLists AS DL ON
DV.ValueId = DL.ValueId
INNER JOIN Firms AS F ON
F.FirmId = J.ClientFirmId
WHERE
DL.DimensionId = 4
GROUP BY
F.FirmID,
F.Name,
DL.ValueName,
DL.ValueId
this produces something like
firmid | value | count
1 1 5
1 2 10
2 3 1
2 1 6
i need to return back the records with 10 and 6.
EDIT : SQL 2005 answer deleted.
Then you could push your results into a temporary table (or table variable) and do something like this...
SELECT
*
FROM
TempTable
WHERE
ValueCount = (SELECT MAX(ValueCount) FROM TempTable AS Lookup WHERE FirmID = TempTable.FirmID)
Or...
SELECT
*
FROM
TempTable
INNER JOIN
(SELECT FirmID, MAX(ValueCount) AS ValueCount FROM TempTable GROUP BY FirmID) AS lookup
ON lookup.FirmID = TempTable.FirmID
AND lookup.ValueCount = TempTable.ValueCount
These will give multiple records if any ValueCount is tied with another for the same FirmID. As such, you could try this...
SELECT
*
FROM
TempTable
WHERE
value = (
SELECT TOP 1
value
FROM
TempTable as lookup
WHERE
FirmID = TempTable.FirmID
ORDER BY
ValueCount DESC
)
For this problem you need to produce the result set of the query in order to determine the Max ValueCount, then you need to do the query again to pull just the records with Max ValueCount. You can do this many way, like repeating the main query as subqueries, and in SQL Server 2005/2008 by using a CTE. I think using the subqueries gets a little messy and would prefer the CTE, but for SQL Server 2000 you don't have that as an option. So, I've used a temp table instead of a CTE. I run it once to get the MaxValueCount and save that into a temp table, then run the query again and join against the temp table to get just the record with MaxValueCount.
create table #tempMax
(
FirmID int,
MaxValueCount int
)
insert #tempMax
SELECT t.FirmID, MAX(t.ValueCount) AS MaxValueCount
FROM (
SELECT F.FirmID, F.Name, DL.ValueId, DL.ValueName
, count(DL.ValueName) AS ValueCount
FROM dbo.Jobs AS J
INNER JOIN DimensionValues AS DV ON DV.CrossRef = J.JobId
INNER JOIN dbo.DimensionLists AS DL ON DV.ValueId = DL.ValueId
INNER JOIN Firms AS F ON F.FirmId = J.ClientFirmId
WHERE DL.DimensionId = 4
GROUP BY F.FirmID, F.Name, DL.ValueName, DL.ValueId) t
SELECT t.FirmID, t.Name, t.ValueID, t.ValueName, t.ValueCount
FROM (
SELECT F.FirmID, F.Name, DL.ValueId, DL.ValueName
, count(DL.ValueName) AS ValueCount
FROM dbo.Jobs AS J
INNER JOIN DimensionValues AS DV ON DV.CrossRef = J.JobId
INNER JOIN dbo.DimensionLists AS DL ON DV.ValueId = DL.ValueId
INNER JOIN Firms AS F ON F.FirmId = J.ClientFirmId
WHERE DL.DimensionId = 4
GROUP BY F.FirmID, F.Name, DL.ValueName, DL.ValueId) t
INNER JOIN #tempMax m ON t.FirmID = m.FirmID and t.ValueCount = m.MaxValueCount
DROP TABLE #tempMax
You should be able to use a derived table for this:
SELECT F.FirmID,
F.Name,
DL.ValueId,
DL.ValueName,
T.ValueCount
FROM Jobs J
INNER JOIN DimensionValues DV
ON DV.Crossref = J.JobID
INNER JOIN DimensionList DL
ON DV.ValueID = DL.ValueID
INNER JOIN Firms F
ON F.FirmID = J.ClientFirmID
--derived table
INNER JOIN (SELECT FirmID, MAX(ValueName) ValueCount FROM DimensionList GROUP BY FirmID) T
ON T.FirmID = F.FirmID
WHERE DL.DimensionId = 4
TBL1 and TBL2 is your query:
SELECT *
FROM TBL1
WHERE
TBL1.ValueCount = (SELECT MAX(TBL2.ValueCount) FROM TBL2 WHERE TBL2.FIRMID = TBL1.FIRMID)