How to get desired result set by SQL query [closed] - sql

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
select * from employee
UNIT_ID PARENT_UNIT TOT_EMP
------- ----------- -------
Oracle IT 10
SAP IT 20
IT PST 30
HRGA FA 5
FA PST 12
How to get output as:
IT 60
ORACLE 10
SAP 20
HRGA 5
FA 17

select a.name, sum(a.tot_emp)
from
(
select unit_id as name, sum(tot_emp) as tot_emp
from employee
group by unit_id
UNION
select parent_id as name, sum(tot_emp) as tot_emp
from employee
group by parent_id
) as a
where exists (select null
from employee e
where e.unit_id = a.name)
group by name;
But this is not a real recursive query (which seems to be what you need), it will work with your sample, but maybe not with real datas (but we don't know the deepness of your hierarchy).

i don't know some detalis. can be in the column UNIT_ID to times the same name?
if not, this is good query:
select e1.UNIT_ID, SUM(TOT_EMP) AS TOT_EMP
from emploee e1
innner join emploee e2
on e1.UNIT_ID = E2.PARENT_UNIT
group by e1.UNIT_ID
if can be same name in the column UNIT_ID, look in the answer of Raphaƫl Althaus. it's good answer.

This is Oracle query:
SELECT unit_id, SUM(total_emp) FROM stack_test
GROUP BY unit_id
/
UNIT_ID SUM(TOTAL_EMP)
-------- --------------
SAP 50
HRGA 15
ORACLE 30
It is always good idea to create tables and populate them with values in your posts...

Related

SQL self join sql query [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am trying to solve below by self join
I have table like this:
Employee Name ReportTo
--------------------------------
Bob Peter
Chris Tim
ABC DEF
Peter Null
EFG Peter
One person have many employee under and there is hierarchy from top level to down. from director to employ. I am trying to create a report to fetch all employees who report to him. Is self join work here or there is any other easy way. I have another condition only top level people can see lower level.
Thanks in advance
Yes a self-join might be used
with Employees ( EmployeeName, ReportTo ) as
(
select 'Bob','Peter' union all
select 'Chris','Tim' union all
select 'ABC','DEF' union all
select 'Peter',Null union all
select 'EFG','Peter'
)
select e1.ReportTo, e1.EmployeeName
from Employees e1
left join Employees e2 on e2.EmployeeName =e1.ReportTo
where e1.ReportTo is not null
order by e1.ReportTo;
ReportTo EmployeeName
--------- ------------
DEF ABC
Peter EFG
Peter Bob
Tim Chris

Postgres how to join table A,B when B is partial to A [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have two tables:
Table A - big table
key,value1
table B - smaller table not all keys exists on this table
keyint, value2
i would like to combine into a third table - table C
key,value1,value2
(where value2 will apear, if exists and if not empty or 0 or NULL)
how do i do that in postgres?
(Added as edit to question by author, so posting as CW here):
I have found the solution:
SELECT key,value1,value2
FROM A as A1
left outer join B on A1.key =B.keyint limit 10000;
The left outer join will take all records from A and put values if they exists on B.

Join a table to bring in another field [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I currently have this query:
select f.chainid,count(f.player_uuid) as Favorites
from deals_player_favorite f
group by f.chainid
order by 2 desc
Which results in:
CHAINID FAVORITES
25 2771
2207 2282
3940 1954
etc...
I have another table called deals_deals, which also includes the CHAINID field. From this table, I want to join a field called VENUE in, so that each CHAIN ID has a Venue description, and the output would look like this
CHAINID VENUE FAVORITES
25 Amazon.com 2771
2207 Walmart 2282
3940 CVS 1954
etc...
How would I properly join the venue field into the query, using CHAIN id as the key that is in both the deals_deals table and deals_player_favorite table.
I tried an inner join which resulted in way too many results.
The deals_deals table has the fields CHAINID and VENUE..
The deals_player_favorite table has the fields CHAINID and PLAYER_UUID, but does not include all of the CHAINIDs that the deals_deals table, only ones that have been accessed by a player_uuid.
SAMPLE DATA:
deals_deals table
VENUE CHAINID
Walmart 235
Aeropostale 1467
Checker's 881
deals_player_favorite table
PLAYER_UUID CHAINID
23rjior23-32fjdf 235
keep in mind that deals_player_favorite only includes specific CHAINIDs that have been clicked on, not ALL chainids....
SELECT F.chainid, V.Venue, COUNT(f.player_uuid) as Favorites
FROM deals_player_favorite F
INNER JOIN Venues V
ON F.chainid = V.chainid
GROUP BY F.chainid, V.Venue
ORDER BY COUNT(f.player_uuid) DESC
If your problem is that you are getting too many records in your count, then you might want to consider using a subquery and then joining the subquery to get the venue:
select f.chainid,
v.venue,
f.Favorites
from
(
select chainid, count(player_uuid) Favorites
from deals_player_favorite
group by chainid
) f
inner join deals_deals v
on f.chainid = v.chainid
See SQL Fiddle with Demo
The subquery will get your total favorites first, then using the chainid you will get the venue

Join columns side by side in result set [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I would like my result to look something like this
FirstName1 LastName1 FirstName2 LastName2
Amy Smith Bob Stone
Fred Joker Gina White
Where FirstName1 and FirstName2 have same data types but nothing I can use to join (assume no one has same names) and the same goes for LastName1 and LastName2.
I tried to create 2 tables. First table contains FirstName1 and LastName1. Second table contains Firstname2 and LastName2.
Then I use
SELECT table1.FirstName1, table1.LastName1, table2.FirstName2, table2.LastName2
FROM table1, table2;
But this gives me a lot of duplicates. Any suggestions?
SELECT t1.FirstName1, t1.LastName1, t2.FirstName2, t2.LastName2
FROM
(SELECT
FirstName1,
LastName1,
ROW_NUMBER() OVER (ORDER BY FirstName1) 'RowNumber'
FROM table1
) AS t1
FULL OUTER JOIN
(SELECT
FirstName2,
LastName2,
ROW_NUMBER() OVER (ORDER BY FirstName2) 'RowNumber'
FROM table2
) AS t2
ON t1.RowNumber = t2.RowNumber
FULL OUTER JOIN will handle the cases where the number of rows from the two tables are not the same.
You should never do what you're trying to do, but try to use DISTINCT
SELECT Distinct
table1.FirstName1,
table1.LastName1,
table2.FirstName2,
table2.LastName2
FROM table1, table2;
The problem with your approach is that the retrieved dataset doesn't make any sense. Why do you want to do it like this anyways?
Edit: you can always do this do this:
select table1.FirstName1, table1.LastName1, table2.FirstName2, table2.LastName2
from table1, table2
where table1.rownum= table2.rownum;
"Oh haha I am really just trying to make it looks pretty. I am used to
programming in C and Java where all kinds of output are pretty
possible. "
Database programming is different. In this realm content is more important than mere prettiness. So when it comes to result sets the database insists that all the columns in a row share a meaningful relationship (the clue is in the name, relational database).
Your problem is, you have no tables with no key in common and hence no way to join the two sets of rows together. Without a proper WHERE clause the database implements a cross join, i.e. a cartesian product, and that's where all the duplication comes from.
Given that you don't have meaningful keys your only option is to fake them; the approach shown by Vikdor is one way to achieve this.

Fetch data with single and fast SQL query

I have the following data:
ExamEntry Student_ID Grade
11 1 80
12 2 70
13 3 20
14 3 68
15 4 75
I want to find all the students that passed an exam. In this case, if there are few exams
that one student attended to, I need to find the last result.
So, in this case I'd get that all students passed.
Can I find it with one fast query? I do it this way:
Find the list of entries by
select max(ExamEntry) from data group by Student_ID
Find the results:
select ExamEntry from data where ExamEntry in ( ).
But this is VERY slow - I get around 1000 entries, and this 2 step process takes 10 seconds.
Is there a better way?
Thanks.
If your query is very slow at with 1000 records in your table, there is something wrong.
For a modern Database system a table containing, 1000 entries is considered very very small.
Most likely, you did not provid a (primary) key for your table?
Assuming that a student would pass if at least on of the grades is above the minimum needed, the appropriate query would be:
SELECT
Student_ID
, MAX(Grade) AS maxGrade
FROM table_name
GROUP BY Student_ID
HAVING maxGrade > MINIMUM_GRADE_NEEDED
If you really need the latest grade to be above the minimum:
SELECT
Student_ID
, Grade
FROM table_name
WHERE ExamEntry IN (
SELECT
MAX(ExamEntry)
FROM table_name
GROUP BY Student_ID
)
HAVING Grade > MINIMUM_GRADE_NEEDED
SELECT student_id, MAX(ExamEntry)
FROM data
WHERE Grade > :threshold
GROUP BY student_id
Like this?
I'll make some assumptions that you have a student table and test table and the table you are showing us is the test_result table... (if you don't have a similar structure, you should revisit your schema)
select s.id, s.name, t.name, max(r.score)
from student s
left outer join test_result r on r.student_id = s.id
left outer join test t on r.test_id = t.id
group by s.id, s.name, t.name
All the fields with id in it should be indexed.
If you really only have a single test (type) in your domain... then the query would be
select s.id, s.name, max(r.score)
from student s
left outer join test_result r on r.student_id = s.id
group by s.id, s.name
I've used the hints given here, and here the query I found that runs almost 3 orders faster than my first one (.03 sec instead of 10 sec):
SELECT ExamEntry, Student_ID, Grade from data,
( SELECT max(ExamEntry) as ExId GROUP BY Student_ID) as newdata
WHERE `data`.`ExamEntry`=`newdata`.`ExId` AND Grade > 60;
Thanks All!
As mentioned, indexing is a powerful tool for speeding up queries. The order of the index, however, is fundamentally important.
An index in order of (ExamEntry) then (Student_ID) then (Grade) would be next to useless for finding exams where the student passed.
An index in the opposite order would fit perfectly, if all you wanted was to find what exams had been passed. This would enable the query engine to quickly identify rows for exams that have been passed, and just process those.
In MS SQL Server this can be done with...
CREATE INDEX [IX_results] ON [dbo].[results]
(
[Grade],
[Student_ID],
[ExamEntry]
)
ON [PRIMARY]
(I recommend reading more about indexs to see what other options there are, such as ClusterdIndexes, etc, etc)
With that index, the following query would be able to ignore the 'failed' exams very quickly, and just display the students who ever passed the exam...
(This assumes that if you ever get over 60, you're counted as a pass, even if you subsequently take the exam again and get 27.)
SELECT
Student_ID
FROM
[results]
WHERE
Grade >= 60
GROUP BY
Student_ID
Should you definitely need the most recent value, then you need to change the order of the index back to something like...
CREATE INDEX [IX_results] ON [dbo].[results]
(
[Student_ID],
[ExamEntry],
[Grade]
)
ON [PRIMARY]
This is because the first thing we are interested in is the most recent ExamEntry for any given student. Which can be achieved using the following query...
SELECT
*
FROM
[results]
WHERE
[results].ExamEntry = (
SELECT
MAX([student_results].ExamEntry)
FROM
[results] AS [student_results]
WHERE
[student_results].Student_ID = [results].student_id
)
AND [results].Grade > 60
Having a sub query like this can appear slow, especially since it appears to be executed for every row in [results].
This, however, is not the case...
- Both main and sub query reference the same table
- The query engine scans through the Index for every unique Student_ID
- The sub query is executed, for that Student_ID
- The query engine is already in that part of the index
- So a new Index Lookup is not needed
EDIT:
A comment was made that at 1000 records indexs are not relevant. It should be noted that the question states that there are 1000 records Returned, not that the table contains 1000 records. For a basic query to take as long as stated, I'd wager there are many more than 1000 records in the table. Maybe this can be clarified?
EDIT:
I have just investigated 3 queries, with 999 records in each (3 exam results for each of 333 students)
Method 1: WHERE a.ExamEntry = (SELECT MAX(b.ExamEntry) FROM results [a] WHERE a.Student_ID = b.student_id)
Method 2: WHERE a.ExamEntry IN (SELECT MAX(ExamEntry) FROM resuls GROUP BY Student_ID)
Method 3: USING an INNER JOIN instead of the IN clause
The following times were found:
Method QueryCost(No Index) QueryCost(WithIndex)
1 23% 9%
2 38% 46%
3 38% 46%
So, Query 1 is faster regardless of indexes, but indexes also definitely make method 1 substantially faster.
The reason for this is that indexes allow lookups, where otherwise you need a scan. The difference between a linear law and a square law.
Thanks for the answers!!
I think that Dems is probably closest to what I need, but I will elaborate a bit on the issue.
Only the latest grade counts. If the student had passed first time, attended again and failed, he failed in total. He/She could've attended 3 or 4 exams, but still only the last one counts.
I use MySQL server. The problem I experience in both Linux and Windows installations.
My data set is around 2K entries now and grows with the speed of ~ 1K per new exam.
The query for specific exam also returns ~ 1K entries, when ~ 1K would be the number of students attended (received by SELECT DISTINCT STUDENT_ID from results;), then almost all have passed and some have failed.
I perform the following query in my code:
SELECT ExamEntry, Student_ID from exams WHERE ExamEntry in ( SELECT MAX(ExamEntry) from exams GROUP BY Student_ID). As subquery returns about ~1K entries, it appears that main query scans them in loop, making all the query run for a very long time and with 50% server load (100% on Windows).
I feel that there is a better way :-), just can't find it yet.
select examentry,student_id,grade
from data
where examentry in
(select max(examentry)
from data
where grade > 60
group by student_id)
don't use
where grade > 60
but
where grade between 60 and 100
that should go faster