How do I generate a table of IDs which have only one attribute each? - sql

I have a table that looks like this
id attribute
1 a
1 a
2 b
2 a
And I want to collect all of the IDs which have ONLY attribute a. So in the example case:
id
1
My initial thought was to use a where, but that would return:
id
1
1
2
Because 2 also has an "a" attribute in one instance.
P.S. I realize the phrasing of the title is ambiguous; maybe there's a better term than attribute to use in this case?

ohh I just saw hive but this is pretty standard sql give it a try.
SELECT
ID
FROM
TABLENAME
GROUP BY
ID
HAVING
COUNT(DISTINCT attribute) = 1
Having is like a where statement after the GROUP BY aggregation has occurred.

HiveQL equivalent of SQL using group by ,having and distinct
select id from (select id,count(distinct attribute) cnt from table_actual group by id having cnt='1') tableouter;

Related

Need sql query to pull back data that meets several groups of criteria from same table in one query

I need to write an sql query that will pull back the data that meets several groups of criteria from the same table. The easiest way to describe is to imagine using an SQL "in" clause but instead of the internals of that clause being "or"s joining the parameters you want it to match it is instead an "and".
I attempted to use count to verify the correct amount of data was pulled back for each "in" statement but the count can't always be trusted due to other entries being similar for each column.
A sample table might be this:
id count animal
--- ----- ------
1 5 puppy
1 6 cat
1 6 puppy
So, now I need a query that will pull back all entries with an id of 1 and a count of 5 and 6 and an animal of puppy and cat. I pretty much need to verify the entire path of the table entry to know I want to pull it back. Is there any built in function that can do this? Do I need to use a recursive CTE to dig deep after confirming that one set of criteria is met? Thanks for any help.
If I got it right
with cnt as(
select id
from tbl
where [count] in (5,6) and animal in ('puppy', 'cat')
group by id
having count(distinct[count])=2 and count(distinct animal)=2
)
select id, [count], animal
from tbl
where id in (select id from cnt);
It's kind of confusing what you're looking for exactly but can you not use or's and ands?
select id, count, animal
from table
where id = 1 and
(count = 5 or count = 6) and
(animal = puppy or anmial = cat)
I think you just want:
select t.*
from t
where id = 1 and
count in (5, 6) and
animal in ('puppy', 'cat');
EDIT:
If you want them all in the same row, just rearrange the conditions:
select t.*
from t
where id = 1 and
( (count = 5 and animal = 'puppy') or
(count = 6 and animal = 'cat')
);

use of min and count from 2 different table in ibm db2

How can i show which tutor teach the least subject?
this is my syntax but I'm getting
Error code 42607
select
tut_id,
min(count(session_code)) as subject_taught
from
tutor,
class
where
tutor.tutor id = class.tut_id
group by tut_id
Expected output:
tut_id subject_taught
id2 1
This is pretty simple:
WITH Subjects_Taught AS (SELECT tutor_id, COUNT(*) AS subjects_taught
FROM Class
GROUP BY tutor_id)
SELECT tutor_id, subjects_taught
FROM Subjects_Taught
WHERE subjects_taught = (SELECT MIN(subjects_taught)
FROM Subjects_Taught)
SQL Fiddle Example
So what's going on in the statement?
First, the Common Table Expression ->
WITH Subjects_Taught AS (SELECT tutor_id, COUNT(*) AS subjects_taught
FROM Class
GROUP BY tutor_id)
This defines an in-query view or temporary table. These are handy for abstracting certain details away, or when you end up referring to the same info twice in a statement (as we do here). Essentially, you end up with a table that looks like this:
id1 | 2
id2 | 1
id3 | 2
... so then the only thing left is to restrict ourselves to rows of this table that meet the minimum:
WHERE subjects_taught = (SELECT MIN(subjects_taught)
FROM Subjects_Taught)
... we reference our virtual table a second time, getting the minimum, as if it were a normal table.
I don't have a DB2 available now but as far as I can see here you cannot nest aggregate functions in DB2:
$... min(count(session_code))...

MySQL - Is it possible to achieve this using SQL?

Imagine you've got a table with 2 columns: ID and NAME. ID is simply a number, incrementing for each row (as you'd expect). NAME is some random varchar string. NAME can be same for different rows. Now, imagine you want to get the 3 latest occurences in this table, where NAME only may occur once.
For example, if you've got this data:
ID NAME
1 HELLO
2 TEST
3 HELLO
4 HELLO
5 QWERTY
6 HELLO
Then the result of the question should be:
6 HELLO
5 QWERTY
2 TEST
Is it possible achieve this on SQL level?
SELECT
MAX(ID),
Name
FROM
table
GROUP BY
Name
ORDER BY
MAX(ID) desc
LIMIT 3
SELECT MAX(ID), NAME
FROM THAT_TABLE
GROUP BY NAME
See: GROUP BY (Aggregate) Functions
I suppose, you need to use "DISTINCT" for the "name" column:
SELECT DISTINCT name, id FROM table_name ORDER BY id DESC LIMIT 3;
Another way to achieve this is to use "GROUP BY" for "name" (see another answer)

Can I write this query using the criteria API or am I stuck with HQL?

I have the following query which I would like to write using the criteria api of NH.
select status, count(1) from (select distinct Status, post_id from post_statistics) tbl group by status
each post_id can exist multiple times in post_statistics
e.g.
id post_id status
1 1 open
1 1 edit
1 1 open
1 2 open
so the query should return the following results:
status count
open 2
edit 1
thx in advance.
mappings, classes?
if i'm thinking right, with a proper mapping this would effectively be something like
(pseudo-HQL)
select stat.Name, count(stat.Posts) from status stat

SQL Order By list of strings?

I wish to do a select on a table and order the results by a certain keyword or list of keywords. For example I have a table like so:
ID Code
1 Health
2 Freeze
3 Phone
4 Phone
5 Health
6 Hot
so rather than just do a simple Order By asc/desc I'd like to order by Health, Phone, Freeze, Hot. Is this possible?
Try using this:
select * from table
order by FIELD(Code, 'Health', 'Phone', 'Freeze', 'Hot')
Here's a horrible hack:
select * from table
order by (
case Code
when 'Health' then 0
when 'Phone' then 1
when 'Freeze' then 2
when 'Hot' then 3
end
)
You can join with the Keywords table, and include a sequence column, and ORDER BY Keyword.Sequence.
Example your keywords table looks like this:
ID Code Sequence
1 Health 1
2 Freeze 3
3 Phone 2
4 Hot 4
Then you can join.
SELECT *
FROM MyTable INNER JOIN
Keywords ON Keywords.ID = MyTable.KeywordID
ORDER BY Keywords.Sequence
Hope this gives you the idea.
Nowadays MySQL has a function called find_in_set()
Use it like this:
select * from table
order by find_in_set(Code,'Health','Phone','Freeze','Hot')
Is this just a one off ORDER BY or something that you're going to want to do often and on more values than specified here?
The order that you have given is arbitrary, therefore an identifier needs to be given to achieve what you want
SELECT
ID,
Code,
CASE Code
WHEN 'Health' THEN 1
WHEN 'Phone' THEN 2
WHEN 'Freeze' THEN 3
WHEN 'Hot' THEN 4
END As OrderBy
FROM Table
ORDER BY
OrderBy
Or
SELECT
ID,
Code
FROM Table
ORDER BY
CASE Code
WHEN 'Health' THEN 1
WHEN 'Phone' THEN 2
WHEN 'Freeze' THEN 3
WHEN 'Hot' THEN 4
END
(I'm not familiar with MySQL but the above would work in SQL Server. The syntax for MySQL won't be too different)
If you're likely to want to do this often, then create an OrderBy column on the table or create an OrderBy table with a FK link to this table and specify an OrderBy numerical field in that.
Hi this is a SQL Server query but I am sure you can do this in MySQL as well:
SELECT ID, Code
FROM x
ORDER BY
CASE Code WHEN 'Health' THEN 1
WHEN 'Phone' THEN 2
WHEN 'Freeze' THEN 4
WHEN 'Hot' THEN 5
ELSE 6 END ASC
, Code ASC
Couple options:
Add OrderCode column with numerical
desired order
Add a table with FK to this table ID
and OrderCode
Yes join your results to your code table and then order by code.CodeOrder
EDIT: Explaing the use of the code table...
Create a separate table of Codes (CodeId, Code, CodeOrder) and join to this and order by CodeOrder. This is nicer than doing the order by (case...) hack suggested since you can easily change the codes and the orders.