Subquery having issues - sql

I am having one issue with sub query. I have to pass multiple ids to my sub query..but with my query i am not getting correct result...
Here is the My sample data and my table structure..
Employee Table:
------------------------
EMPLOYEE_ID NOT NULL NUMBER(16)
EXTERNAL_ID_1 VARCHAR2(200)
EXTERNAL_ID_2 VARCHAR2(200)
JOB_PROFILE_TYPE VARCHAR2(4)
FIRST_NAME NOT NULL VARCHAR2(200)
MIDDLE_NAME VARCHAR2(200)
Alignment Table :
-------------------------
ALIGNMENT_ID NOT NULL NUMBER(16)
TEAM_ID NOT NULL NUMBER(16)
EMPLOYEE_ID NUMBER(16)
ALIGNMENT_NAME NOT NULL VARCHAR2(200)
EXTERNAL_ID_1 VARCHAR2(200)
STATUS NOT NULL VARCHAR2(4)
STATUS_CHANGE_DATE NOT NULL DATE
MANAGER_ALIGNMENT_ID NUMBER(16)
Event table :
-------------------
EVENT_ID NOT NULL NUMBER(16)
EMPLOYEE_ID NOT NULL NUMBER(16)
AFFILIATION_ID NUMBER(16)
CUSTOMER_ID NUMBER(16)
EXTERNAL_ID_1 VARCHAR2(200)
Sample data :
ALIGNMENT_ID ALIGNMENT_NAME EMPLOYEE_ID ROLE MANAGER_ALIGNMENT_ID
1006034672 SII-KRN-BANG-A01 17452000001661 REP 1006034513
1006034673 SII-KRN-BANG-A02 18910000219453 REP 1006034513
1006034674 SII-KRN-BANG-A03 60000001963804 REP 1006034513
1006034675 SII-KRN-BANG-A05 60000001963706 REP 1006034514
1006034676 SII-KRN-BANG-A06 18910000081856 REP 1006034514
1006034677 SII-KRN-BANG-B01 60000001963699 REP 1006034513
My Query :
SELECT *
FROM event ev
INNER JOIN employee e ON e.employee_id=ev.employee_id
INNER JOIN alignment a ON e.employee_id=a.employee_id AND alignment_id in(:alignment_id)
Description :
I have the data stored in alignment table with child records and parent records. In alignment table I have the data alignment_id and manager alignment_id.
For each rep there should one manager.(manager_alignment_id).
I have to integrate this query to front end..
In front end I have drop down values and will select multiple ids to pass to this query...
if the selection for alignment_id(rep) then no problem. If they will select manager_alignment_id then how to pass this value to mu query.
I am using oracle 11g version.

This may be the query you're looking for:
SELECT *
FROM employee E
INNER JOIN alignment A ON A.employee_id = E.employee_id
AND (A.manager_alignment_id = <Your value here>
OR A.alignment_id = <Your value here>)
This query returns every rows corresponding to the defined manager_alignment_id or alignment_id.
Hope this will help you.

Related

Cross Reference Columns ORACLE SQL

I am having trouble selecting all values from a table.
I need to select all vehicles where their vRentTimes value is the same as the times they appear in the Renting table.
So basically just checking if the recordings of rentings are correct.
This is the description of tables:
Vehicle
Name Null? Type
------------ -------- ------------
VPLATENUMBER NOT NULL VARCHAR2(7)
VCOLOR NOT NULL VARCHAR2(10)
VCC NOT NULL NUMBER
VHORSEPOWER NOT NULL NUMBER
VRENTTIMES NUMBER
VEHCATNAME NOT NULL VARCHAR2(20)
Renting
Name Null? Type
------------ -------- -----------
CAFM NOT NULL VARCHAR2(9)
VPLATENUMBER NOT NULL VARCHAR2(7)
OUTDATE NOT NULL DATE
INDATE DATE
I see. vRentTimes is supposed to be a count for the second table. You can use JOIN and `aggregation. To get the rows that do not match:
select v.*, r.cnt
from vehicles v left join
(select VPLATENUMBER, count(*) as cnt
from renting r
group by VPLATENUMBER
) r
on r.VPLATENUMBER = v.VPLATENUMBER
where v.VRENTTIMES <> coalesce(cnt, 0);

How to join two or more tables without a 'common column' in sql

Here is my question from a homework assignment from class that has been giving me some trouble.
Display the month in which more than 5 employees joined in any department located in Syndey.
PS: I apologize for the caps. My teacher instructed me to create the tables like that.
Table locations:
LOCATION_ID NOT NULL NUMBER(4)
STREET_ADDRESS VARCHAR2(40)
POSTAL_CODE VARCHAR2(12)
CITY NOT NULL VARCHAR2(30)
STATE_PROVINCE VARCHAR2(25)
COUNTRY_ID CHAR(2)
Table jobs:
JOB_ID NOT NULL VARCHAR2(10)
JOB_TITLE NOT NULL VARCHAR2(35)
MIN_SALARY NUMBER(6)
MAX_SALARY NUMBER(6)
Job_history:
JOB_ID NOT NULL VARCHAR2(10)
JOB_TITLE NOT NULL VARCHAR2(35)
MIN_SALARY NUMBER(6)
MAX_SALARY NUMBER(6)
Table employees:
EMPLOYEE_ID NOT NULL NUMBER(6)
FIRST_NAME VARCHAR2(20)
LAST_NAME NOT NULL VARCHAR2(25)
EMAIL NOT NULL VARCHAR2(25)
PHONE_NUMBER VARCHAR2(20)
HIRE_DATE NOT NULL DATE
JOB_ID NOT NULL VARCHAR2(10)
SALARY NUMBER(8,2)
COMMISSION_PCT NUMBER(2,2)
MANAGER_ID NUMBER(6)
DEPARTMENT_ID NUMBER(4)
Table Departments:
DEPARTMENT_ID NOT NULL NUMBER(4)
DEPARTMENT_NAME NOT NULL VARCHAR2(30)
MANAGER_ID NUMBER(6)
LOCATION_ID NUMBER(4)
First of all, please don't be apologetic about using caps in SQL scripts. Your teacher is teaching you correct guidelines. It is actually a recommended way (the clean-code way) to write your SQL scripts in capital letters especially SQL keywords and data types for better readability. If you want to keep even your column names in capital then that is your choice.
Well here is your query to get the desired output. You have not mentioned the database you are currently targeting. I've written my query targeting Microsoft SQL Server database.
SELECT HiredMonth,COUNT(HiredMonth)
FROM
(
SELECT DATENAME(MONTH,E.HIRE_DATE) AS HiredMonth
FROM Employees E
INNER JOIN Departments D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID
INNER JOIN Locations L ON D.LOCATION_ID = L.LOCATION_ID
WHERE CITY = 'Sydney') AS P
Group BY P.HiredMonth
P.S. If you are targeting some other database then few built-in functions used in my query like DATENAME might have to be changed accordingly to make this query compilable in other database.

How to solve this SQL query (header and detail)?

I am working with SQL Server 2008 R2.
I have a SQL query question related to header and detail tables. I have a header table where I am storing location & department & week_start_date. I have a detail table where I am storing employee_id & job_code & work_date & hours.
I want to find those employees who are in different headers with same week_start_date but different location and/or department.
Here is the explanation:
I have a header table:
CREATE TABLE header (
header_id bigint not null PRIMARY KEY,
location_code int not null,
department_code int not null,
week_start_date datetime not null )
I have a detail table:
CREATE TABLE detail (
detail_id bigint not null PRIMARY KEY,
header_id bigint not null FOREIGN KEY header(header_id),
employee_id int not null,
job_code int not null,
work_date datetime not null,
hours decimal(8,2) not null )
header table has the unique key as location_code + department_code + week_start_date.
For example this is the data in header table:
header_id=11, location_code=22, department_code=33,
week_start_date='2016-02-08'
header_id=12, location_code=22, department_code=39,
week_start_date='2016-02-08'
header_id=13, location_code=22, department_code=33,
week_start_date='2016-02-15'
header_id=14, location_code=21, department_code=33,
week_start_date='2016-02-08'
Each row in header table can have multiple rows in detail table.
detail table has the unique key as header_id + employee_id + job_code + work_date.
For example this is the data in detail table for 1000598 employee_id:
detail_id=101, header_id=11, employee_id=1000598, job_code=77,
work_date='2016-02-08', hours=5.00
detail_id=102, header_id=11, employee_id=1000598, job_code=77,
work_date='2016-02-09', hours=4.00
detail_id=109, header_id=12, employee_id=1000598, job_code=79,
work_date='2016-02-11', hours=4.50
For example this is the data in detail table for 1000599 employee_id:
detail_id=121, header_id=11, employee_id=1000599, job_code=78,
work_date='2016-02-10', hours=8.00
detail_id=122, header_id=14, employee_id=1000599, job_code=75,
work_date='2016-02-12', hours=3.00
For example this is the data in detail table for 1000600 employee_id:
detail_id=131, header_id=11, employee_id=1000600, job_code=72,
work_date='2016-02-11', hours=7.00
detail_id=132, header_id=13, employee_id=1000600, job_code=75,
work_date='2016-02-17', hours=3.00
The SQL query should return 1000598 employee_id as 1000598 has data for both department_code=33 and department_code=39 for the same week_start_date='2016-02-08'.
The SQL query should return 1000599 employee_id as 1000599 has data for both location_code=22 and location_code=21 for the same week_start_date='2016-02-08'.
The SQL query should not return 1000600 employee_id.
This is the start I have come up with:
select
h.employee_id,
d.week_start_date
from
header h (nolock)
inner join detail d (nolock)
on h.header_id = d.header_id
group by
h.employee_id,
d.week_start_date
order by
1,
2
Not much.
I want to find those employees who are in different headers with same
week_start_date but different location and/or department.
The query below will return all (employee_id, week_start_date) pairs that have more than 1 location_code or department_code
select d.employee_id, h.week_start_date
from detail d
join header h on h.header_id = d.header_id
group by d.employee_id, h.week_start_date -- employees with same week_start_date
having (
count(distinct h.location_code) > 1 -- have more than 1 location
or count(distinct h.department_code) > 1 -- or more than 1 department
)
select dtl.* from
(select * from detail d1 where EXISTS(select count(header_id) from detail d2 where d1.employee_id=d2.employee_id having count(header_id)>1))
inner join
header hd
on hd.header_id=dtl.header_id
group by dtl.employee_id, hd.week_start_date
having count(*)>1

Join logic from two separate tables in sql

We returned a list of cardID's after a query and those cardID's belong to two tables Student and Personnel. So how can I join those cardID's with Student and Personnel so I can return a table that shows name of Student and Personnel according to cardID's?
Personnel table:
PERSONNELID NUMBER(9,0)
PERSONNELNAME VARCHAR2(20)
PERSONNELSURNAME VARCHAR2(20)
PERSONNELJOB VARCHAR2(40)
PERSONNELCARDID NUMBER(4,0)
Student table:
STUDENTID NUMBER(9,0)
STUDENTNAME VARCHAR2(20)
STUDENTSURNAME VARCHAR2(20)
STUDENTDEPT VARCHAR2(40)
STUDENTFACULTY VARCHAR2(20)
STUDENTCARDID NUMBER(4,0)
CardID table
CARDID NUMBER(4,0)
USERTYPE VARCHAR2(20)
CHARGE NUMBER(3,2)
CREDIT NUMBER(4,2)
PaymentDevice table:
ORDERNO NUMBER
PAYDEVIP NUMBER(8,0)
PAYDEVDATE DATE No
PAYDEVTIME VARCHAR2(8)
CHARGEDCARDID NUMBER(9,0)
MEALTYPE VARCHAR2(10)
I tried to return first 10 person's name and surname that eat at cafeteria on 27/12/2012
SELECT C.CARDID
FROM CARD C, PAYMENTDEVICE P
WHERE P.ORDERNO
BETWEEN (SELECT MIN(ORDERNO)
FROM PAYMENTDEVICE
WHERE PAYDEVDATE='27/12/2012') AND (SELECT MIN(ORDERNO)
FROM PAYMENTDEVICE
WHERE PAYDEVDATE='27/12/2012')+10 AND C.CARDID=P.CHARGEDCARDID;
Our orderNo isn't reset everyday but keeps increasing so we found the min orderNo that day and add 10 to this value to find first 10 person who eat on that day between those order numbers.
So what return from this query:
CARDID
1005
1000
1002
1003
1009
2000
2001
1007
2002
1004
1006
and those some of those cardId (start with 1) are studentCardId and some of them (starts with 2) are PersonnelCardId. So how can I match and write names accordingly?
SELECT *
FROM Personel p INNER JOIN Student s
ON p.PersonnelCardId = s.StudentCardId
INNER JOIN ReturnedQuery rq
ON rq.CardId = p.PersonnelCardId
updated:
SELECT p.PersonnelName, rq.CardId
FROM Personel p INNER JOIN ReturnedQuery rq
ON rq.CardId = p.PersonnelCardId
UNION
SELECT s.StudentName, rq.Cardid
FROM Student s INNER JOIN ReturnedQuery rq
ON s.StudentCardId = rq.Cardid
Your original query is actually pretty fragile. I'd rewrite it like so (and added the needed joins):
WITH First_Daily_Purchase as (SELECT chargedCardId,
MIN(payDevTime) as payDevTime,
MIN(orderNo) as orderNo
FROM PaymentDevice
WHERE payDevDate >=
TO_DATE('2012-12-27', 'YYYY-MM-DD')
AND payDevDate <
TO_DATE('2012-12-28', 'YYYY-MM-DD')
GROUP BY chargedCardId),
First_10_Daily_Purchasers as (SELECT chargedCardId
FROM (SELECT chargedCardId,
RANK() OVER(ORDER BY payDevTime,
orderNo) as rank
FROM First_Daily_Purchase) a
WHERE a.rank < 11)
SELECT a.chargedCardId, b.personnelName, b.personnelSurname
FROM First_10_Daily_Purchasers a
JOIN Personnel b
ON b.personnelCardId = a.chargedCardId
UNION ALL
SELECT a.chargedCardId, b.studentName, b.studentSurname
FROM First_10_Daily_Purchasers a
JOIN Student b
ON b.studentCardId = a.chargedCardId
(Have a working SQL Fiddle - generally bullet-proofing this took me a while.)
This should get you the first 10 people who made a purchase (not the first 11 purchases, which is what you were actually getting). This of course assumes that payDevTime is actually stored in a sortable format (if it isn't you have bigger problems than this query not working quite right).
That said, there's a number of troubling things about your schema design.

SQL Query (maybe simple)

So i'm having this problem.
I have two tables (Oracle), one is called Destination and the other one Reserve. Reserve has a foreign key to the id of Destination (Because on reserve has one destination). And reserve tuples means all the reserves that all the users have done. I need a way to check the top 3 most visited Destinations (based on the foreign key in the table Reserve).
How can I do that with SQL in Oracle. I know that I need to search within the Reserve tables for the 3 most repeated Destinations ID's, and later join that with the Destination table to get the details of the top 3 destinations.
Any help is valid. Thank you very much.
SCHEMA:
--------------------------------------------------------
-- File created - martes-septiembre-15-2009
--------------------------------------------------------
--------------------------------------------------------
-- DDL for Table DESTINO
--------------------------------------------------------
CREATE TABLE "S2501A29"."DESTINO"
( "PK_ID_DESTINO" NUMBER(10,0),
"FK_COD_UBICACION_GEOGRAFICA" NUMBER(10,0),
"NOMBRE" VARCHAR2(10),
"FOTO" VARCHAR2(30),
"DESCRIPCION" VARCHAR2(50)
) ;
--------------------------------------------------------
-- DDL for Table LUGAR_ESTADIA
--------------------------------------------------------
CREATE TABLE "S2501A29"."LUGAR_ESTADIA"
( "PK_ID_ESTADIA" NUMBER(10,0),
"NOMBRE" VARCHAR2(10),
"TIPO" VARCHAR2(10),
"DESCRIPCION" VARCHAR2(50),
"COSTO_SERVICIOS" NUMBER,
"DESCRIPCION_ALOJAMIENTO" VARCHAR2(100),
"DESCRIPCION_ALIMENTACION" VARCHAR2(100)
) ;
--------------------------------------------------------
-- DDL for Table OPCION_TRANSPORTE
--------------------------------------------------------
CREATE TABLE "S2501A29"."OPCION_TRANSPORTE"
( "PK_ID_VIAJE" NUMBER(10,0),
"MEDIO_TRANSPORTE" VARCHAR2(10),
"RESPONSABLE" VARCHAR2(10),
"CIUDAD_ORIGEN" VARCHAR2(10),
"CIUDAD_DESTINO" VARCHAR2(10),
"COSTO" NUMBER
) ;
--------------------------------------------------------
-- DDL for Table RESERVA
--------------------------------------------------------
CREATE TABLE "S2501A29"."RESERVA"
( "PK_ID_RESERVA" NUMBER(10,0),
"FK_COD_DESTINO" NUMBER(10,0),
"FK_COD_ESTADIA" NUMBER(10,0),
"FK_COD_VIAJE" NUMBER(10,0),
"TARJETA_CREDITO" VARCHAR2(12),
"FECHA_SALIDA" DATE,
"FECHA_REGRESO" DATE,
"NOMBRE_USUARIO" VARCHAR2(50)
) ;
--------------------------------------------------------
-- DDL for Table UBICACION_GEOGRAFICA
--------------------------------------------------------
CREATE TABLE "S2501A29"."UBICACION_GEOGRAFICA"
( "PK_ID_UBICACION" NUMBER(10,0),
"CIUDAD" VARCHAR2(10),
"PAIS" VARCHAR2(10),
"CONTINENTE" VARCHAR2(10)
) ;
Just a note:
RESERVE is Reserva
DESTINATION is Destino
Because the DB is in spanish. Thanks!
Maybe I'm missing something, but what about grouping by foreign key and sorting by the resulting values?
Edit: Something like:
select FK_COD_DESTINO, count(*) as qty from RESERVA group by FK_COD_DESTINO order by qty desc limit 3
Oracle doesn't support limit. This should work for you.
select A.FK_COD_DESTINO
, A.COUNT
, A.RANK
, B.*
from (select FK_COD_DESTINO
, count(*) as COUNT
, rank() over (order by count(*) desc) as RANK
from RESERVA
group by FK_COD_DESTINO) A
join DESTINO B on B.PK_ID_DESTINO = A.FK_COD_DESTINO
where A.RANK <= 3
you can try HAVING rownum <=3
How about:
WITH CountsByDestination
AS
(
SELECT FK_COD_DESTINO,
COUNT(*) CNT
FROM Reservations
GROUP BY DestinationId
),
RankingByDestination
AS
(
SELECT FK_COD_DESTINO,
CNT,
RANK() OVER (ORDER BY CNT) RNK
FROM CountsByDestination
)
SELECT *
FROM RankingByDestination R
INNER JOIN Destinations D ON D.PK_ID_DESTINO = R.FK_COD_DESTINO
WHERE R.RNK BETWEEN 1 AND 3
ORDER BY R.RNK
This retains ties, so if two or more destinations share the same counts they should appear as part of the result set.