Returned by a subquery - database

GOAL
I have a table A with column NAME, I would like that whenever column NAME of table A, is equal to column NAME of table B, is selected in column CODE_CLIENT of table B
QUERY
SELECT
CASE WHEN name = (select name from tb_get_names)
THEN (select code_client from tb_get_names)
ELSE 'null'
END AS Result FROM tb_get_clients
OUTPUT
ERROR: more than one row returned by a subquery used as an expression

Each of the 2 subqueries you use, return all the names or all the code_clients of the table tb_get_names. This is why you get the error.
You need a LEFT JOIN:
SELECT
c.name,
n.code_client AS Result
FROM tb_get_clients AS c LEFT JOIN tb_get_names AS n
ON n.name = c.name

Related

SQL Server: COUNT used with WHERE

so I'd consider myself really new to SQL Server so the less used keywords like HAVING and COUNT() etc. So when I got this error:
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.
I was really confused by the last bit. "a select list?" "column being aggregated is an outer reference?" Can anyone explain this in layman's terms?
It's basically saying you need to use a subquery that references another table if you want to use aggregates in those places:
SELECT A,
B,
C
FROM Table T
WHERE A = (SELECT MAX(D) FROM Table T2 WHERE T2.A = T.A)
--Valid, MAX(D) is an outer reference to another table we call T2
SELECT A,
B,
C
FROM Table T
WHERE A = MAX(D) --Invalid
The HAVING version would be something like this:
SELECT A,
B,
C
FROM Table T
GROUP BY A,
B,
C
HAVING COUNT(*) > (SELECT MAX(D) FROM Table T2) --Valid
SELECT A,
B,
C
FROM Table T
GROUP BY A,
B,
C
HAVING COUNT(*) > MAX(D) --Invalid
The SELECT-list is
SELECT a, b, c ... <=== this list of expressions after SELECT
An outer reference is a column of the surrounding query referenced in a subquery. This is clearly explained here: Aggregates with an Outer Reference
Note that the WHERE-clause is applied before grouping (with GROUP BY) and the HAVING-clause after grouping. Therefore the aggregate functions can appear in the HAVING-clause but not in the WHERE clause.
SELECT customer_id, COUNT(*) as number_of_orders, SUM(amount) AS total_amount
FROM cust_orders
WHERE year(order_date) = 2017 -- filters records before grouping.
GROUP BY customer_id -- groups while counting and summing up.
HAVING COUNT(*) > 2 -- count is available here.
This selects all the customer orders of the year 2017 and calculates the totals per customer. Only customers having more than 2 orders in this year are returned.
Basically what it says is that you cannot do this:
WHERE COUNT(ColumnA) = 100
You need a HAVING after the GROUP BY:
SELECT COUNT(ColumnA) AS CountA, ColumnB, ColumnC
FROM Table
GROUP BY ColumnB, ColumnC
HAVING COUNT(ColumnA) = 100

Need help MSSQL query to bring table with two columns into one showing unique value of field 1 and corresponding values in field 2 (in that order)?

Picture of current state and desired state
Need help MSSQL query to bring table with two columns into one showing unique value of field 1 and corresponding values in field 2 (in that order)? See picture attached in link above
Your request sounds quite strange, but if you want to do it, one way is to use rollup + grouping_id like this:
select case when grouping_id(field2) = 1 then field1 else field2 end
from yourtable
group by field1, rollup(field2)
order by field1, grouping_id(field2) desc, field2
Usually you'd use this for subtotals, but using it with case you can add additional rows to the data.
This will return:
x
a
b
c
d
y
e
f
g
z
h
i
Edit: How to list table + column names:
select case when grouping_id(c.name) = 1 then t.name else c.name end
from sys.tables t join sys.columns c on t.object_id = c.object_id
group by t.name, rollup(c.name)
order by t.name,c.name

Exclude records for column A when B is null

Need help with a query that will let me exclude a record from column A if a record in column exist with a null.
Let's say i have two rows is column A named "test" they have column B values of 1 and null respectively. Here below is a query that I'm working on Object ID is column A and endversion is column B on my scenario.
select b.PortID,
max(endversion)as EndVersion,
d.ShortName as RuleName
from xr.ObjectPropertyValue a
join moxyportfolio b on a.objectid=b.portkey
join xr.AssignAllObjectsRule c on a.Objectclassid=c.ObjectClassID -- can replace with xr.assignobjectrule if it's rule is not assigned to all portfolios.
join xr.rulebase d on c.RuleID=d.RuleID
where objectid in (select objectid from xr.objectpropertyvalue where endversion is not null)
group by a.ObjectId, b.portid,d.ShortName
You can do this using HAVING:
select
b.PortID,
max(endversion) as EndVersion,
d.ShortName as RuleName
from xr.ObjectPropertyValue a
join moxyportfolio b
on a.objectid = b.portkey
join xr.AssignAllObjectsRule c
on a.Objectclassid = c.ObjectClassID -- can replace with xr.assignobjectrule if it's rule is not assigned to all portfolios.
join xr.rulebase d
on c.RuleID = d.RuleID
group by a.ObjectId, b.portid, d.ShortName
having sum(case when endversion is null then 1 else 0 end) = 0
Only select values for column A if column B is not null (and nothing otherwise):
SELECT COLA
FROM TABLE
WHERE COLB IS NOT NULL
Only select a value for column A if column B is not null (and null otherwise):
SELECT CASE WHEN COLB IS NOT NULL THEN COLA ELSE NULL END AS COLA
FROM TABLE

Ignore condition in WHERE clause when column is NULL

I do have table were one row (with Type =E) is related to another row.
I have written query to return COUNT of those related rows. The problem is that there is no explicit relationship (like ID column that would clearly say which row is related to other row). Therefore I am trying to find relationship based on multiple conditions in WHERE clause.
The problem is that in few cases, the columns A and B could be NULL (for records where TYPE = 'M'). In such a cases I would like to ignore that condition, so It would use only first 3 conditions to determine relationship.
I have tried CASE Statement but is not working as expected:
SELECT [T1].[ID],[T1].[AlphaId],[T1].[Type],[T1].[A],[T1].[B],[T1].[Date],[T1].[ServiceID]
,( SELECT COUNT(*)
FROM MyTable T2
WHERE [T1].[AlphaId]=[T2].[AlphaId] AND
[T1].[Date]=[T2].[Date] AND
[T1].[ServiceID]=[T2].[ServiceID] AND
[T2].[A]=CASE WHEN [T2].[A] IS NULL THEN NULL ELSE [T1].[A] END AND
[T2].[B]=CASE WHEN [T2].[B] IS NULL THEN NULL ELSE [T1].[B] END AND
[T2].[Type]='M'
) as TotalCount
FROM MyTable T1
WHERE [T1].[Type] = 'E'
I can't ignore that condition, as for some cases the Date, ServiceID could be same, however it's the A, B which differs them. Luckily where A, B IS NULL, it is the Date, ServiceID which differs those two records.
http://sqlfiddle.com/#!3/c98db/1
Many thanks in advance.
You could join the tables and use COUNT and GROUP BY to get the counts. Then you can JOIN [A] and [B] if they are equal or NULL.
SELECT [T1].[ID],[T1].[AlphaId],[T1].[Type],[T1].[A],[T1].[B],[T1].[Date],[T1].[ServiceID], count([T2].[ID])
FROM MyTable T1
INNER JOIN MyTable T2 ON [T1].[AlphaId]=[T2].[AlphaId] AND
[T1].[Date]=[T2].[Date] AND
[T1].[ServiceID]=[T2].[ServiceID] AND
([T2].[A]= [T1].[A] OR [T2].[A] IS NULL )AND
([T2].[B]= [T1].[B] OR [T2].[B] IS NULL )AND
[T2].[Type] <> [T1].[Type]
WHERE [T1].[Type] = 'E'
GROUP BY [T1].[ID],[T1].[AlphaId],[T1].[Type],[T1].[A],[T1].[B],[T1].[Date],[T1].[ServiceID]

T-SQL: Can a subquery in the SELECT clause implicitly reference a table in the main outer query?

In T-SQL, is it possible to have a subquery in the SELECT clause that implicitly references tables in the main, outer query? For example:
select NAME,
case when exists (select o.ORDERID) then 1 else 0 end BUYER
from CUSTOMER c
left join ORDER o
on c.CUSTID = o.CUSTID
In other words, can I write subqueries without a FROM clause?
Intellisense seems to recognize outer table aliases in subqueries, but I can't find any documentation that says this is acceptable T-SQL. I can certainly run some of my own tests, but I also wanted to check with the community. Thanks.
Yes this is valid syntax.
A SELECT without a FROM is treated as though selecting from a single row table. Referencing columns from the outer query is required for correlated sub queries and is perfectly valid there.
The particular query you have makes no sense though. It will always evaluate to 1 as that subquery always returns a single row (with a single column containing the corresponding o.OrderId) going into the EXISTS check.
Probably you want to check o.OrderId IS NULL
SELECT NAME,
CASE
WHEN o.ORDERID IS NULL THEN 0
ELSE 1
END BUYER,
FROM CUSTOMER c
LEFT JOIN ORDER o
ON c.CUSTID = o.CUSTID
Where it does make sense to use this type of syntax is in a null safe equality check.
e.g.
SELECT A,
B,
CASE
WHEN EXISTS (SELECT T.A
EXCEPT
SELECT T.B) THEN 1
ELSE 0
END AS DistinctFrom
FROM T
Is equivalent to
SELECT A,
B,
CASE
WHEN A <> B
OR ( A IS NULL
AND B IS NOT NULL )
OR ( A IS NOT NULL
AND B IS NULL ) THEN 1
ELSE 0
END AS DistinctFrom
FROM T

Resources