SQLPlus - Stored procedure that displays the number of items sold in descending order - sqlplus

I'm in a bit of a bind - I want to make a stored procedure that displays the number of each item sold and orders them from most to least. The relevant data comes from two different tables:
ITEMS | itemid | itemname
SALES | itemdid
I can display the itemid and count of each item sold with this query:
SELECT * FROM (
SELECT ITEMID,
COUNT (ITEMID) AS COUNTOF
FROM SALES GROUP BY ITEMID
ORDER BY COUNTOF DESC);
I can display the itemname of each item sold with this one:
SELECT ITEMS.ITEMNAME
FROM ITEMS
JOIN SALES
ON SALES.ITEMID = ITEMS.ITEMID;
However, I can not seem to get the itemname to display next to the count of the item sold. I'm really struggling with this. Thanks

What you are looking for is a JOIN or INNER JOIN.
SELECT s.ITEMID,i.ITEMNAME, COUNT (s.ITEMID) AS COUNTOF FROM SALES AS s
INNER JOIN ITEMS AS i ON i.itemid=s.itemid
GROUP BY s.ITEMID,i.ITEMNAME
ORDER BY COUNTOF DESC

Related

Can anyone help me in this dbms query?

The Question-
Write a query to display the name(s) of the students who have secured the maximum marks in each subject, ordered by subject name in ascending order. If there are multiple toppers, display their names in alphabetical order.
Display it as subject_name and student_name.
O/P: first column - subject_name
second column - student_name
My answer-
select su.subject_name,st.student_name from subject su,student st,mark m
where m.student_id = st.student_id and m.subject_id = su.subject_id
and m.value = (select max(value) from mark group by subject_id);
Error-
and m.value = (select max(value) from mark group by subject_id)
*
ERROR at line 3:
ORA-01427: single-row subquery returns more than one row
What i know is I will have to make another subquery something like
and m.value =(select..... (select max(value) from mark group by subject_id));
But I am not getting it.
Nevermind got the answer, we will have to use IN operator and club value, subject_id as they are a set.
SELECT su.subject_name, st.student_name
FROM student s
JOIN mark m ON st.student_id = m.student_id
JOIN subject su ON m.subject_id = su.subject_id
WHERE (m.value, su.subject_id) IN (
SELECT max(value), subject_id FROM mark GROUP BY subject_id
)
ORDER BY su.subject_name, st.student_name;

SQL placement join with student, friend, package

Issue:
You are given three tables: Students, Friends and Packages.
Students contains two columns: ID and Name.
Friends contains two columns: ID and Friend_ID (ID of the ONLY best friend).
Packages contains two columns: ID and Salary (offered salary in $ thousands per month).
Write a query to output the names of those students whose best friends got offered a higher salary than them. Names must be ordered by the salary amount offered to the best friends. It is guaranteed that no two students got same salary offer.
Code:
This is the code that I have come up with but it does not produce correct results. Can anyone let me know why?
select TableA.name
from
(select s.id,s.name,p.salary from students s inner join packages p on s.id=p.id) TableA,
(select f.id,f.friend_id, p2.salary from friends f inner join packages p2 on f.friend_id=p2.id) TableB
where TableA.id=TableB.id And TableA.salary>TableB.salary
order by TableB.salary desc;
I think in your query you wrote AND TableA.salary < TableB.salary instead of AND TableA.salary > TableB.salary.
Moreover I think your query can be written in a more synthetic way.
On MSSQL (but it works on MYSQL too, as query is very basic), you can try to use this one:
SELECT s.id
,s.NAME
,p.salary
, f.friend_id, p2.salary as friend_salary
FROM students s
INNER JOIN packages p ON s.id = p.id
LEFT JOIN friends f ON f.id = s.id
LEFT JOIN packages p2 ON f.friend_id = p2.id
WHERE p.salary <= p2.salary
ORDER BY s.id;
Output:
id NAME salary friend_id friend_salary
1 John 1000 2 1200
3 Pete 800 1 1000
Sample data:
CREATE TABLE students (id int, NAME VARCHAR(30));
CREATE TABLE packages (id int, salary INT);
CREATE TABLE friends (id int, friend_id INT);
INSERT INTO students values (1,'John');
INSERT INTO students values (2,'Arthur');
INSERT INTO students values (3,'Pete');
INSERT INTO packages values (1,1000);
INSERT INTO packages values (2,1200);
INSERT INTO packages values (3,800);
INSERT INTO friends values (1,2);
INSERT INTO friends values (2,3);
INSERT INTO friends values (3,1);
I used CTE for easy code readability. I am not sure whether it is fully optimized or not. But, it yields the result as expected from the question.
with std_salary as (
SELECT s.id, s.name, p.salary
FROM Students s
JOIN Packages p
ON s.id=p.id),
friend_salary as (
SELECT f.id, p.salary
FROM Friends f
JOIN Packages p
ON f.friend_id=p.id
)
SELECT name
FROM
(SELECT std_salary.name, std_salary.salary as own, friend_salary.salary as friend
FROM std_salary
JOIN friend_salary
ON std_salary.id=friend_salary.id) as final
WHERE final.own<final.friend
ORDER BY final.friend;
This worked for me in MS SQL
SELECT a.name
FROM (SELECT students.id as main_id, students.name, packages.salary
FROM students join packages on students.id = packages.id) a
JOIN (SELECT f.id as main_id1, p.salary
FROM friends f JOIN packages p ON f.friend_id = p.id) b
ON a.main_id = b.main_id1
WHERE b.salary>a.salary
ORDER BY b.salary ASC;
you have written 'where TableA.salary>TableB.salary' implying that you want to find rows where your salary is > than your friends. But the question asked was the opposite (to find names where the firends salary is > than your salary) so you can change that to 'where TableB.salary>TableA.salary' and it should work.
select my_name from
(select s.id as my_id,s.name my_name,p.salary as my_salary from students s
inner join packages p on s.id=p.id) as my_tbl inner join (select f.id as
id,f.friend_id as frnd_id,p.salary as frnd_salary from friends f inner join
packages p on f.friend_id=p.id ) as frnd_tbl on my_id=id where
frnd_salary>my_salary order by frnd_salary;

Optimizing SQL query using JOIN instead of NOT IN

I have a sql query that I'd like to optimize. I'm not the designer of the database, so I have no way of altering structure, indexes or stored procedures.
I have a table that consists of invoices (called faktura) and each invoice has a unique invoice id. If we have to cancel the invoice a secondary invoice is created in the same table but with a field ("modpartfakturaid") referring to the original invoice id.
Example of faktura table:
invoice 1: Id=152549, modpartfakturaid=null
invoice 2: Id=152592, modpartfakturaid=152549
We also have a table called "BHLFORLINIE" which consists of services rendered to the customer. Some of the services have already been invoiced and match a record in the invoice (FAKTURA) table.
What I'd like to do is get a list of all services that either does not have an invoice yet or does not have an invoice that's been cancelled.
What I'm doing now is this:
`SELECT
dbo.BHLFORLINIE.LeveringsDato AS treatmentDate,
dbo.PatientView.Navn AS patientName,
dbo.PatientView.CPRNR AS patientCPR
FROM
dbo.BHLFORLINIE
INNER JOIN dbo.BHLFORLOEB
ON dbo.BHLFORLOEB.BhlForloebID = dbo.BHLFORLINIE.BhlForloebID
INNER JOIN dbo.PatientView
ON dbo.PatientView.PersonID = dbo.BHLFORLOEB.PersonID
INNER JOIN dbo.HENVISNING
ON dbo.HENVISNING.BhlForloebID = dbo.BHLFORLOEB.BhlForloebID
LEFT JOIN dbo.FAKTURA
ON dbo.BHLFORLINIE.FakturaId = FAKTURA.FakturaId
WHERE
(dbo.BHLFORLINIE.LeveringsDato >= '2017-01-01' OR dbo.BHLFORLINIE.FakturaId IS NULL) AND
dbo.BHLFORLINIE.ProduktNr IN (110,111,112,113,8050,4001,4002,4003,4004,4005,4006,4007,4008,4009,6001,6002,6003,6004,6005,6006,6007,6008,7001,7002,7003,7004,7005,7006,7007,7008) AND
((dbo.FAKTURA.FakturaType = 0 AND
dbo.FAKTURA.FakturaID NOT IN (
SELECT FAKTURA.ModpartFakturaID FROM FAKTURA WHERE FAKTURA.ModpartFakturaID IS NOT NULL
)) OR
dbo.FAKTURA.FakturaType IS NULL)
GROUP BY
dbo.PatientView.CPRNR,
dbo.PatientView.Navn,
dbo.BHLFORLINIE.LeveringsDato`
Is there a smarter way of doing this? Right now the added the query performs three times slower because of the "not in" subquery.
Any help is much appreciated!
Peter
You can use an outer join and check for null values to find non matches
SELECT customer.name, invoice.id
FROM invoices i
INNER JOIN customer ON i.customerId = customer.customerId
LEFT OUTER JOIN invoices i2 ON i.invoiceId = i2.cancelInvoiceId
WHERE i2.invoiceId IS NULL

Hive join query returning Cartesian product on inner join

I am doing inner join on two tables that are created using Hive. One is a big table "trades_bucket" and another is a small table "counterparty_bucket". They are created as follows :-
DROP TABLE IF EXISTS trades_bucket;
CREATE EXTERNAL TABLE trades_bucket(
parentId STRING,
BookId STRING) CLUSTERED BY(parentId) SORTED BY(parentId) INTO 32 BUCKETS;
DROP TABLE IF EXISTS counterparty_bucket;
CREATE EXTERNAL TABLE counterparty_bucket(
Version STRING,AccountId STRING,childId STRING)
CLUSTERED BY(childId ) SORTED BY(childId) INTO 32 BUCKETS;
The Join between the tables
SELECT /*+ MAPJOIN(counterparty_bucket) */ BookId , t.counterpartysdsid, c.sds
FROM counterparty_bucket c join trades_bucket t
on c.childId = t.parentId
where c.childId ='10001684'
The problem is that the join is producing Cartesian product out of the two tables. What I mean is if big table has 100 rows and small table has 4 rows for a given id, I expect the join to return 100 rows, but I am getting back 400 rows. Anyone have a clue or anyone witnessed similar situation?

I am unable to use minus keyword in oracle 9i!

select salary from employees order by salary desc
MINUS
select salary from employees where rownum<10 order by salary desc;
I am unable to use order by with MINUS ,it says sql command not properly ended.
Please suggest!
Given what the business question seems to be (show the salaries of employees where the salary is not in the top ten of salaries) I would think analytics would be a choice worth considering:
select salary
from (select salary,
rank() over (order by salary) as salary_rank
from employees
)
where salary_rank > 10
order by salary;
Using analytics would also only scan EMPLOYEES once, whereas the original query would scan it twice.

Resources