Splitting out rows with multiple values in SQL - sql

I am trying to split out few values from a database.
There are two columns, Test and Test_Parameter. I want to extract those rows which have different "test_parameter" values for same "Test" value. For example, in my screenshot, I want "Grade:" to be selected as it has different values of Test_Parameter. I know it has a very simple solution but I am not able to figure it out.

You can use aggregation and having:
select test
from t
group by test
having min(test_parameter) <> max(test_parameter);

I might be confused by the ask, but wouldn't this work?
SELECT *
FROM t
WHERE test <> test_parameter

Try any of below to remove colon and compare :
SELECT DISTINCT test FROM table1 WHERE test NOT LIKE test_parameter||'%'
SELECT DISTINCT test FROM table1 WHERE SUBSTR(test,1,INSTR(test,':')-1) <> test_parameter

I like Gordon's answer better, but a maybe simple you understand albeit I suspect slower method would be:
SELECT test
FROM (
SELECT test,
COUNT(DISTINCT(test_parameter) AS c
FROM table1
GROUP BY 1
)
WHERE c > 1
the above is if you really don't want the counts in the results, otherwise the having clause makes its simpler:
SELECT test,
COUNT(DISTINCT(test_parameter) AS c
FROM table1
GROUP BY 1
HAVING c > 1

Related

PostgreSQL Error more than one row returned by a subquery used as an expression

I have a problem with a data query where I query a single column like this:
SELECT a.ad_morg_key, count(a.sid_mpenduduk_key) AS total_population
FROM sid_mpenduduk a
GROUP BY a.ad_morg_key;
and it really works. But when I query with multiple columns with a query like this:
SELECT a.ad_morg_key, b."name",
count(b.sid_magama_key) AS total,
count(b.sid_magama_key)::float / (SELECT count(a.sid_mpenduduk_key)
FROM sid_mpenduduk a
GROUP BY a.ad_morg_key)::float * 100::float AS percentage,
(SELECT count(a.sid_mpenduduk_key) FROM sid_mpenduduk a GROUP BY a.ad_morg_key) AS total_population
FROM sid_mpenduduk a
INNER JOIN sid_magama b ON a.sid_magama_key = b.sid_magama_key
GROUP BY a.ad_morg_key, b."name";
But it fails with:
ERROR: more than one row returned by a subquery used as an expression
I want the final result like this :
Your subquery is grouped by a.ad_morg_key so it will get you a row for each different value of a.ad_morg_key.
In general terms each subquery in a SELECT statement should return a single value. Suppose you have the following table called A.
A_key
A_value
A1
200
A2
200
If you execute
SELECT (SELECT A_KEY FROM A) as keys
FROM A
the subquery (SELECT A_KEY FROM A) returns
A_key
A1
A2
so what should be the value for keys?
SQL cannot handle this decision so you should pick one of the values or aggregate them into a single value.
Use a correlation clause instead:
(SELECT count(a.sid_mpenduduk_key)
FROM sid_mpenduduk a2
WHERE a2.ad_morg_key = a.ad_morg_key
) AS total_population
I'm not sure if the subquery is really necessary. So, you might consider asking a new question with sample data, desired results, and a clear explanation of what you are trying to do.
You're getting burned by
GROUP BY ...
(SELECT count(a.sid_mpenduduk_key)
FROM sid_mpenduduk a
GROUP BY a.ad_morg_key) AS total_population
because the outer GROUP BY wants a scalar, but the subquery is producing a count for each a.ad_morg_key.
I don't write my queries that way. Instead, produce a virtual table,
SELECT a.ad_morg_key, b."name",
...
JOIN
(SELECT ad_morg_key,
count(sid_mpenduduk_key) as N
FROM sid_mpenduduk
GROUP BY ad_morg_key) AS morgs
on ad_morg_key = morgs.ad_morg_key
That way, you have the count for each row as N, and you can divide at will,
count(b.sid_magama_key)::float / morgs.N
and, if you get tripped up, you'll have many more rows than you expected instead of an error message.

How to use the results of one query in the next query?

I have read answers here but I am still not quite sure how I would do this regarding two columns of a table and more than one result per query.
So, the first query would look like this in my Node app:
select stype, lid from Profiles where lid_P=${profile.lid} and stype_P='${profile.stype}';
// result can consist of 1-50 objects
I need the result for the following query:
select * from an where stype=stype and lid=lid;
// where lid and stype are results from the other query
I only need the results of the second query but I fail to implement only one query doing both. Can someone help me out? Any help is appreciated.
Thank you!
You seem to want exists:
select *
from an a
where exists(
select 1
from profiles p
where
p.stype = a.stype and p.lid = s.lid
and p.lid_p = #profile_lid and p.style_p = #profile_stype
)
#profile_lid and #profile_stype are the parameters to the query - that I would recommend using instead of concatenating variables in the query string.
Did you try
select *
from an
where (stype, lid) in (select distinct ... <your first query>)

Two SELECT-Statement work alone but not together

I have two select statements that work on their own, but not together.
This:
SELECT MAX(a2.Fachanzahl)
FROM C17_AbfrageBView a2;
works and returns one row with one column with the value 2
This:
SELECT a1.PersonID, a1.Vorname, a1.Nachname, MAX(a1.Fachanzahl) Fachanzahl
FROM C17_AbfrageBView a1
GROUP BY a1.PersonID, a1.Vorname, a1.Nachname
HAVING MAX(a1.Fachanzahl) = 2;
works and returns the correct row.
However, this:
SELECT a1.PersonID, a1.Vorname, a1.Nachname, MAX(a1.Fachanzahl) Fachanzahl
FROM C17_AbfrageBView a1
GROUP BY a1.PersonID, a1.Vorname, a1.Nachname
HAVING MAX(a1.Fachanzahl) = (
SELECT MAX(a2.Fachanzahl)
FROM C17_AbfrageBView a2
);
does not return anything (it should return the same row as the above statement), even though the outer and inner select statements work on their own. What is the problem here?
Thank you!
I cannot think of a mechanism where this would happen. As far as I know, MAX() does not change the type of a column, ruling out things like float rounding errors or collation incompatibilities.
I can say that the query would be more efficient if written using WHERE rather than HAVING:
SELECT DISTINCT a1.PersonID, a1.Vorname, a1.Nachname, a1.Fachanzahl
FROM C17_AbfrageBView a1
WHERE a1.Fachanzahl = (SELECT MAX(a2.Fachanzahl)
FROM C17_AbfrageBView a2
);
If the MAX() is introducing some problem with nano-changes to the value, then this might fix the problem.
Because you only care about the maximum value (at least in the query in the question), you can filter first. This makes the query much more efficient. The difference between SELECT DISTINCT and GROUP BY should be between nothing and negligible. The former is easier to type.

Emulate subquery with no main table in access

I can do this in SQL Server:
SELECT 'HERRAMIENTA ELÉCTRICA' AS TIPO_PRODUCTO,
0 AS DEPRECIACION,
(select sum(empid) from HR.employees) STOCK
but in Access the same query show me the next error:
Query input must contain at least one table or query
So which could be the best form to emulate this? Make a query with any other table looks dirty for me.
EDIT 1:, HR.employees It may no have data, but i want show constants ('HERRAMIENTA ELÉCTRICA',''0') and 0 in the third column, maybe using isnull and this is not the problem here.
Why not to select directly:
select 'HERRAMIENTA ELÉCTRICA' AS TIPO_PRODUCTO,
0 AS DEPRECIACION,
IIF(ISNULL(sum(empid)), 0, sum(empid)) AS STOCK
from HR.employees
This simply doesn't work in Access. You need a FROM clause.
So you need to have a dummy table with one record, even if you don't use a single field from that table.
SELECT 'HERRAMIENTA ELÉCTRICA' AS TIPO_PRODUCTO,
0 AS DEPRECIACION,
(select sum(empid) from HR.employees) STOCK
FROM Dummy_Table
Using this example as empty table:
with employ as
(select 2 as col from dual
minus
select 2 as col from dual)
The query is this one:
select 'HERRAM' as tipo,
0 as deprec,
coalesce(sum(col), 0) as STOCK
from employ;
coalesce(x, value) sets the column to value when X is null
In Access, you can use a system table, and Val and Nz for the zero value:
SELECT TOP 1
'HERRAMIENTA ELÉCTRICA' AS TIPO_PRODUCTO,
0 AS DEPRECIACION,
Val(Nz((select sum(empid) from HR.employees), 0)) AS STOCK
FROM
MSysObjects

designedly big value in SQL

Ok, I have to put null values last. The query should run under Oracle and MySQL.
I've already came up with
ORDER BY
CASE WHEN some_table.ord IS NULL THEN 9999999999 ELSE some_table.ord END
I should use value > max(some_table.ord) instead of 9999999999.
I think subquery to determine this value is too ugly here.
If this was C++ I can use some macro like INT_MAX for this purpose. Can you name its cross-DBMS SQL twin?
UPDATE
the question is if can I put something .. beautiful instead of 9999999999, so that query will work both in Oracle and MySQL,
not how to put null values last
Use an extra column for the null flag:
order by
case when some_table.ord is null then 2 else 1 end ,
some_table.ord
Or, if you have enough knowledge of the values that this column can take, just hard-code a number that is larger than anything in there:
order by coalesce(some_table.ord, 9999999999)
In Oracle, it's simply
ORDER BY some_table.ord NULLS LAST
Something like the following might work:
SELECT S.VAL1, S.VAL2, S.VAL3, COALESCE(S.ORD, O.MAX_ORD+1) AS ORD
FROM SOME_TABLE S,
(SELECT MAX(ORDER) AS MAX_ORD FROM SOME_TABLE) O
WHERE S.whatever = whichever AND
S.something <> something_else
ORDER BY ORD
Not sure if MySQL allows sub-queries in the FROM list. The idea here is to avoid the use of a magic value to handle the NULL case.
Share and enjoy.