Getting data having only same values in all rows in DB2 - sql

I have 2 tables in DB2:
1) users ==> basic user details
2) details ==> more user details
The "details" table has columns named ssn, company and super_company. The company and super_company column can have multiple values for the same SSN.
Problem: I am trying to fetch only the users which has same super_company for the ssn.
I need username,ssn and company_id in output.
I tried grouping but not sure how to proceed as I am new to DB2.
SQL Fiddle: http://www.sqlfiddle.com/#!2/6d378/1/0
Please note that sql fiddle does not support DB2. I have provided just for providing the table structure.

You can use this query
select U.account_id, U.username from users U
join details D
on U.account_id = D.account_id
group by U.account_id, U.username
having count(distinct super_company) = 1
SQL FIDDLE

You say that you want company in the output, but you do not say what to do when there are multiple companies. Here is one method that outputs one row per user with an arbitrary company:
select u.username, u.accound_id, d.ssn as ssn,
min(d.company) as company, min(d.super_company)
from users u join
details d
on u.accound_id = d.accound_id
group by u.username, u.accound_id
having min(d.super_company) = max(d.super_company);
Actually aggregating multiple company values into a string is harder than it should be in DB2. You can get the individual records for matching users as well. I would do this using window functions:
select username, accound_id, ssn, company, super_company
from (select u.username, d.*,
min(super_company) over (partition by ssn) as minsc,
max(super_company) over (partition by ssn) as maxsc
from users u join
details d
on u.accound_id = d.accound_id
) t
where minsc = maxsc;
This is closer to your specific question, which is about duplicates by ssn, because it does not include username and accound_id when looking for duplicates.

select d.*, u.*
from details d
join users u
on u.accound_id = d.accound_id
join (
select accound_id
from details
group by accound_id
having count(distinct super_company) = 1
) x
on x.accound_id = u.accound_id

Related

Show rows with at least one occurrence in a relation table?

I have the following table schema:
user (id, name, alias, password, active, mail, age)
comment(id, news(FK), user(FK), text, date)
new_cat(news(FK), category(FK))
I'm trying to select all the users who have commented on AT LEAST one new of EVERY category.
This is what I'm trying without any success:
SELECT * FROM user AS u, comment AS c
WHERE u.id = c.user AND c.news IN (SELECT news FROM new_cat);
I believe this is not iterating properly and checking for EVERY category and just checks if the condition applies just on one category.
How can I properly do this?
Join the tables, group by user and set the condition in the HAVING clause.
If there is a category table where you store all the categories:
SELECT u.*
FROM user u
INNER JOIN comment c ON c.user = u.id
INNER JOIN new_cat n ON n.news = c.news
GROUP BY u.id
HAVING COUNT(DISTINCT n.category) = (SELECT COUNT(*) FROM category);

Select name from SQL column

I am trying to select the names (along with the rest of the information on the table such as data, time, lesson) of each user that is inside a users table. The names I'm trying to select are the ones that are on the same row as a particular teacherID. However when I run this code I'm getting the same name for all records, when I should be getting two different ones.
SELECT FName, SName, bookedLessons.bookedHour,
bookedLessons.bookedDate, bookedLessons.lesson
FROM users JOIN bookedLessons
WHERE teacherID = 11
AND users.userID = (SELECT userID FROM bookedLessons WHERE teacherID = 11)
Your join needs an ON clause but not the subquery in the WHERE clause:
SELECT u.FName, u.SName, b.bookedHour, b.bookedDate, b.lesson
FROM bookedLessons b INNER JOIN users u
ON u.userID = b.userID
WHERE b.teacherID = 11

Getting Counts Per User Across Tables in POSTGRESQL

I'm new to postgresql. I have a database that has three tables in it: Users, Order, Comments. Those three tables look like this
Orders Comments
------ --------
ID ID
UserID UserID
Description Details
CreatedOn CreatedOn
I'm trying to get a list of all of my users and how many orders each user has made and how many comments each user has made. In other words, the result of the query should look like this:
UserID Orders Comments
------ ------ --------
1 5 7
2 2 9
3 0 0
...
Currently, I'm trying the following:
SELECT
UserID,
(SELECT COUNT(ID) FROM Orders WHERE UserID=ID) AS Orders,
(SELECT COUNT(ID) FROM Comments WHERE UserID=ID) AS Comments
FROM
Orders o,
Comments c
WHERE
o.UserID = c.UserID
Is this the right way to do this type of query? Or can someone provide a better approach from a performance standpoint?
SQL Fiddle
select
id, name,
coalesce(orders, 0) as orders,
coalesce(comments, 0) as comments
from
users u
left join
(
select userid as id, count(*) as orders
from orders
group by userid
) o using (id)
left join
(
select userid as id, count(*) as comments
from comments
group by userid
) c using (id)
order by name
The usual way to do this is by using outer joins to the two other tables and then group by the id (and name)
select u.id,
u.name,
count(distinct o.id) as num_orders,
count(distinct c.id) as num_comments
from users u
left join orders o on o.userId = u.id
left join comments c on c.userId = u.id
group by u.id, u.name
order by u.name;
That might very well be faster than your approach. But Postgres' query optimizer is quite smart and I have seen situations where both solutions are essentially equal in performance.
You will need to test that on your data and also have a look at the execution plans in order to find out which one is more efficient.

SQL Query to find the value which has max number of occurrences in a table without nesting

I'm working on the following schema (bold text stands for pk, and ":" stand for referenced tables) :
USERS(username, name, surname);
PRODUCTS(id, name, quantity);
PURCHASES(user:USERS, product:PRODUCTS, dateAndTime, quantityPurchased);
I want to find name and surname of the user who has made the max number of purchases.
Firstly I use a nested query to find out the number of purchases for each user and then I select the user which purchased >= ALL those values:
SELECT name, surname, username
FROM users JOIN purchases ON username = user
GROUP BY name, surname, username
HAVING count(*) >= ALL(
SELECT count(*)
FROM utenti JOIN acquisti ON username = user
GROUP BY username)
Is there another way to achieve the same without using nested queries?
Thank you in advance for your time.
Yes there is. This sounds like a homework assignment, but you seem to have put some work into it. The idea is to order by the count(*) and take the first row. The syntax in SQL Server, Sybase, and Access is:
SELECT top 1 name, surname, username
FROM users as u INNER JOIN
purchases as p
ON u.username = p.user
GROUP BY name, surname, username
ORDER BY count(*) desc;
Other databases would put a limit 1 clause after the order by, instead of top 1. And others may have even more arcane syntax.
This will return the user with most purchased items.
SELECT TOP 1
U.name, U.surname, SUM(P.quantityPurchased) Purchases
FROM users U
JOIN purchases P
on U.username= P.user
GROUP BY U.username, U.name, U.surname
ORDER BY Purchases DESC
and this will return the user with most purchaes.
SELECT TOP 1
U.name, U.surname, COUNT(*) occurrences
FROM users U
JOIN purchases P
on U.username= P.user
GROUP BY U.username, U.name, U.surname
ORDER BY occurrences DESC

SQL query to find out the number of tickets

I have two tables in MS Access.
Table 1: users
ID (auto int)
Name
Table 2: tickets
ID (auto int)
userName (int) (refers to ID in users table)
How can I list the user names and the number of tickets submitted?
This should give you the results that you want. You will want to use an aggregate function COUNT() and a GROUP BY
SELECT u.name, count(t.username) TicketsSubmitted
FROM Users u
INNER JOIN tickets t
ON u.id = t.username
GROUP BY u.name
Count the tickets per user in a subquery, then list all the info per user.
SELECT u.Name AS UserName, t.ticketCount AS TicketsSubmitted
FROM users AS u
INNER JOIN ( SELECT COUNT(ID), userName AS ticketCount FROM tickets GROUP BY userName ) AS t
ON u.ID = t.userName
Should do it.
A make table query should allow you to query those two tables and create a third with the data you want.
The following link from the Microsoft Office website should give you the information you need.
http://office.microsoft.com/en-us/access-help/create-a-make-table-query-HA010108505.aspx
The two answers above give solid advice for the query to get the data you want.