Having count in SELECT clause - sql

Find the names of cities that hosts both SALES and TRANSPORT departments
For my oracle database have this table
i.) DEPTLOC
//DEPTLOC
CITY DNAME
---------------------
NEWYORK IT
NEWYORK COMPUTER
LONDON Science
LONDON SALES
LONDON TRANSPORT
For my SQL select statement
SELECT CITY FROM DEPTLOC
WHERE
DEPTLOC.DNAME='SALES' OR DEPTLOC.DNAME='TRANSPORT'
GROUP BY
CITY
HAVING COUNT(*)=2;
the output always display
no rows selected.
My output should be
DNAME
--------
LONDON

For things like this, I try to use a simple join to the same table. First, I would have an index on the table by (City, DName).. then
select
d.City
from
deptLoc d
JOIN deptLoc d2
on d.city = d2.city
AND d2.dname = 'TRANSPORT'
where
d.dname = 'SALES'
It may look strange, but think about it. The outer portion WHERE clause only cares about cities that have ONE of the qualifiers. Why even count cities that dont even have that. So, now the join. Since you know the first qualifier on SALES is covered, re-join to the dept loc table again, but on the same city name AND the second instance is ALSO that of your 'TRANSPORT' component. You will be surprised at how fast it would be, especially on a large dataset.

can you try this :
SELECT CITY FROM DEPTLOC
WHERE
trim(DEPTLOC.DNAME)='SALES' OR trim(DEPTLOC.DNAME)='TRANSPORT'
GROUP BY
CITY
HAVING COUNT(*)=2;
I think in your data you have some different chars like space or new lines
you can check it

i think this could be a better query.
SELECT CITY
FROM DEPTLOC
WHERE
DEPTLOC.DNAME in ('SALES','TRANSPORT')
GROUP BY CITY

Related

SQL query to list cities in which employee did not work

SQL query to list cities in which employee did not work from below
"employee" table:
name
city
srini
seattle
ross
atlanta
rich
redmond
Example: if I give "srini", query should return "Atlanta" and "Redmond"
I tried below 2 queries with no luck, it returns empty results:
SELECT t1.city
FROM employee t1
JOIN employee t2 ON t1.name=t2.name
WHERE t1.city != t2.city
WHERE name='srini'
SELECT city
FROM (SELECT city FROM employee WHERE name='srini') as e1
WHERE city <> e1.city
This should work:
select distinct city
from employee
where city not in
(select city
from employee
where name = 'srini')
Basically it's selecting all city names that don't exist in a row where name is 'srini'
SQL is such fun. I'd go with a GROUP BY query, where I use the HAVING clause to only return cities where no srini lives.
select city
from employee
group by city
having sum(case when name = 'srini' then 1 else 0 end) = 0
Core ISO/ANSI SQL, i.e. every dbms is expected to support it.
Or use EXCEPT:
select city from employee
EXCEPT
select city from employee where name = 'srini'
Core ISO/ANSI SQL, i.e. every dbms is expected to support it.

SQL employee / company/country

I have three tables
Country (country id - country name - country pop)
City (city id - city name - city code - city pop)
Company (city code - company name - company employee)
Company employee is the number of employee.
I must present a table with the SUM of the employees that has each company in country level.
I have used the following query
SELECT country_name, company_name, company_employee
FROM country,
city,
company
WHERE country.country_id = city.country_id
and city.city_code = company.city_code
I took a table in which you can see the country, the company and the number of employee
(e.g. In one country UK the same company ACS has 2 records ACS 300 EMPLOYEE & ACS 100 EMPLOYEE instead of one record ACS 400 employee)
I believe that something is missing from my code. I have tried use functions such as sum and group but it failed.
Is this what you want?
SELECT cy.country_name, co.company_name, SUM(co.company_employee)
FROM company co JOIN
city ci
ON ci.city_code = co.city_code JOIN
country cy
ON cy.country_id = ci.country_id
GROUP BY cy.country_name, co.company_name;
Note the use of proper, explicit, modern, standard JOIN syntax. Never use commas in the FROM clause. This is particularly important if you are learning SQL; you should learn to use the language correctly.

Select single row or multiple rows based on condition

I'm trying to identify a student's home district by joining a student's zip code to a district zip code. A given district may overlap several zip codes, so several possible home districts may appear for the student. For example, Zip code 99999 may include the Houston and Sugarland school districts. I can narrow down the home district to a single record when the student's city has the same name as the district name as for example if the student's city is Houston and the district name is Houston. In that case, I only want to retrieve the Houston district, not both Houston and Sugarland. However, if the student happened to live in Bayou with the zip code of 99999, then I'd want to retrieve both Houston and Sugarland districts since I don't have a fix on the district. I've tried several approaches but cannot come up with a solution. Here's
a primitive attempt:
Select S.Name, S.City, S.Zip, D.DistrictName
From tblStudent S
Left Join tblDistrict D on D.zip=S.zip
Where
(Case
When D.DistrictName=S.City then D.DistrictName
Else D.DistrictName
End)=D.DistrictName
Any suggestions are greatly appreciated!
You can try selecting each case separately and then making a union of the two queries.
Case 1: District Name equals City Name
Case 2: There is no District Name that is equal to the City Name
Something like this:
Select S.Name, S.City, S.Zip, D.DistrictName
From tblStudent S
Inner Join tblDistrict D on D.zip=S.zip and D.DistrictName = S.City
Union
Select S.Name, S.City, S.Zip, D.DistrictName
From tblStudent S
Inner Join tblDistrict D on D.zip=S.zip
Where not exists (
Select D2.* from tblDistrict D2
Where D2.DistrictName = S.City
And D2.zip = S.zip
)
SQL Fiddle: http://sqlfiddle.com/#!9/06d6d7/2/0

SELECT count(*) then output empty or not empty with yes or no

Find if SALES department has its locations in exactly the same cities as TRANSPORT department"(assume that an empty result means YES and any nonempty result means NO)
In my database got this table.
//DEPTLOC
DNAME CITY
----------------
SALES LONDON
TRANSPORT LONDON
TRANSPORT BOSTON
SCIENCE BOSTON
Not sure how to write the query but at least i try
SELECT COUNT(*) FROM DEPTLOC WHERE
(DNAME='SALES' AND DNAME='TRANSPORT') AND
How should i write after the AND operator in sql in order to get output something like this
//Display
YES . (<--- LONDON , got SALES and TRANSPORT in same cities)
You can use decode
SELECT Decode(Count(*), 0, 'No',
'Yes')
FROM {rest of your query}
DECODE compares expr to each search value one by one. If expr is equal to a search, then Oracle Database returns the corresponding result. If no match is found, then Oracle returns default. If default is omitted, then Oracle returns null.
To pick up whether you have sales and transport you should use a self join.
By aliasing the DEPTLOC table as 'sales' and 'transport' and joining on the city name you will get a list of the city which have both sales & transport.
SELECT sales.CITY
FROM DEPTLOC sales
INNER JOIN DEPTLOC transport ON sales.CITY = transport.CITY
WHERE sales.DNAME = 'SALES'
AND transport.DNAME = 'TRANSPORT'
To get a list of yes and no you can use the above as a sub-query and use a case statement. I have added the distinct clause to eliminate any duplicate entries.
SELECT DISTINCT CITY,
CASE WHEN salesandtransport.CITY IS NULL THEN 'NO' ELSE 'YES' END as DISPLAY
FROM DEPTLOC
LEFT JOIN
(SELECT sales.CITY AS CITY
FROM DEPTLOC sales
INNER JOIN DEPTLOC transport ON sales.CITY = transport.CITY
WHERE sales.DNAME = 'SALES'
AND transport.DNAME = 'TRANSPORT') salesandtransport ON DEPTLOC.CITY = salesandtransport.CITY
There are many ways to approach this problem. The following uses full outer join to compare the two sets of cities. The idea is that any non-matching city will produce a NULL value. This is detecting by comparing count(*) to count(xx.City):
select (case when count(*) = count(dls.City) and count(*) = count(dlt.City)
then 'Yes'
else 'No'
end)
from DeptLoc dls full outer join
DeptLoc dlt
on dls.Dname = 'Sales' and dlt.Dname = 'Transport' and dls.City = dlt.City;
I think you should group by CITY and output Cities where count of DEPTS is not equal to count of DEPTS you need (2 in this case):
SELECT CASE WHEN
EXISTS(SELECT CITY FROM DEPTLOC
WHERE DNAME IN('SALES','TRANSPORT')
GROUP BY CITY
HAVING COUNT(*)<>2
)
THEN 'NO'
ELSE 'YES'
END
FROM DUAL;
SQL Fiddle demo
This simple query should work just fine for you:
SELECT CITY,'YES' FROM DEPTLOC
WHERE CITY IN(SELECT CITY FROM DEPTLOC WHERE DNAME='TRANSPORT')
AND DNAME ='LOCATION'
OUTPUT will have those cities those have both transport and location and look like:
LONDON YES
I guess, this is what you are after:
SELECT CITY,COUNT(*),CASE WHEN COUNT(*)>2 THEN 'YES' ELSE 'NO' END AS STATUS
FROM DEPTLOC WHERE
(DNAME='SALES' OR DNAME='TRANSPORT')
AND CITY='LONDON'
GROUP BY CITY
Result:
CITY COUNT(*) STATUS
LONDON 2 YES
See result in SQL Fiddle.
EXPLANATION:
STATUS field will be YES only if it returns 2 rows for that city. .i.e., 1 for Sales and 1 for Transport.
This question is a little bit ambiguous, but I now think that this is what is asked: Give 'YES' if for all cities where there is a SALES, there is also a TRANSPORT, and NO otherwise.
I believe this query should achieve this.
SELECT CASE WHEN Cnt = 0 THEN 'NO' ELSE 'YES' END AS Answer FROM
(SELECT COUNT(*) AS Cnt FROM DUAL
WHERE NOT EXISTS
(SELECT * FROM DeptLoc dl
WHERE dl.DName = 'SALES' AND NOT EXISTS
(SELECT * FROM DeptLoc
WHERE City = dl.City AND DName = 'TRANSPORT')));
Modified from SQL Fiddle by Raging Bull: http://www.sqlfiddle.com/#!4/ff7a8/1
Here's another alternative. A FULL OUTER JOIN is made between the rows having DNAME as SALES and TRANSPORT. Their differences are found if there are any rows with CITY as NULL in the other set, as follows:
SELECT DECODE(COUNT(*), 0, 'YES', 'NO') Display
FROM
(
SELECT s.DNAME as s_DNAME, s.CITY as s_CITY, t.DNAME as t_DNAME, t.CITY as t_CITY
FROM
(SELECT DNAME, CITY
FROM DEPTLOC
WHERE DNAME = 'SALES') s
FULL OUTER JOIN
(SELECT DNAME, CITY
FROM DEPTLOC
WHERE DNAME = 'TRANSPORT'
) t
ON s.CITY = t.CITY
WHERE s.CITY IS NULL OR t.CITY IS NULL
);
Here's the SQL Fiddle.
The SQL Fiddle also contains a query to list the cities with only SALES or TRANSPORT.

Minimizing SQL queries using join with one-to-many relationship

So let me preface this by saying that I'm not an SQL wizard by any means. What I want to do is simple as a concept, but has presented me with a small challenge when trying to minimize the amount of database queries I'm performing.
Let's say I have a table of departments. Within each department is a list of employees.
What is the most efficient way of listing all the departments and which employees are in each department.
So for example if I have a department table with:
id name
1 sales
2 marketing
And a people table with:
id department_id name
1 1 Tom
2 1 Bill
3 2 Jessica
4 1 Rachel
5 2 John
What is the best way list all departments and all employees for each department like so:
Sales
Tom
Bill
Rachel
Marketing
Jessica
John
Pretend both tables are actually massive. (I want to avoid getting a list of departments, and then looping through the result and doing an individual query for each department). Think similarly of selecting the statuses/comments in a Facebook-like system, when statuses and comments are stored in separate tables.
You can get it all in a single query with a simple join, e.g.:
SELECT d.name AS 'department', p.name AS 'name'
FROM department d
LEFT JOIN people p ON p.department_id = d.id
ORDER BY department
This returns all the data, but it's a bit of a pain to consume, since you'll have to iterate through every person anyway. You can go further and group them together:
SELECT d.name AS 'department',
GROUP_CONCAT(p.name SEPARATOR ', ') AS 'name'
FROM department d
LEFT JOIN people p ON p.department_id = d.id
GROUP BY department
You'll get something like this as the output:
department | name
-----------|----------------
sales | Tom, Bill, Rachel
marketing | Jessica, John
SELECT d.name, p.name
FROM department d
JOIN people p ON p.department_id = d.id
I suggest also reading a SQL Join tutorial or three. This is a very common and very basic SQL concept that you should understand thoroughly.
This is normally done in a single query:
SELECT DepartmentTable.Name, People.Name from DepartmentTable
INNER JOIN People
ON DepartmentTable.id = People.department_id
ORDER BY DepartmentTable.Name
This will suppress empty departments. If you want to show empty departments, change INNER to LEFT OUTER