SELECT DISTINCT
at.AccountId AS AccountId,
a.FirstName + ' ' + a.LastName AS [FullName],
DATEDIFF(day, T.ArrivalDate, T.ReturnDate) AS LongestTrip,
DATEDIFF(day, T.ArrivalDate, T.ReturnDate) AS ShortestTrip
FROM
Accounts a
JOIN
AccountsTrips at ON a.Id = AT.AccountId
JOIN
Trips t ON T.Id = AT.TripId
WHERE
a.MiddleName IS NULL AND t.CancelDate IS NULL
ORDER BY
DATEDIFF(day, T.ArrivalDate, T.ReturnDate) DESC, ShortestTrip ASC
The code only orders the tables descending in LongestTrip and in ShortestTrip
SAMPLE DATA !
Find the longest and shortest trip for each account, in days. Filter the results to accounts with no middle name and trips, which are not cancelled (CancelDate is null).
Order the results by Longest Trip days (descending), then by Shortest Trip (ascending).
Examples
AccountId FullName LongestTrip ShortestTrip
------------------------------------------------------------
40 Winna Maisey 7 1
56 Tillie Windress 7 1
57 Eadith Gull 7 1
66 Sargent Rockhall 7 1
69 Jerome Flory 7 2
… … … …
The Tables are --
CREATE TABLE Cities
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(20) NOT NULL,
CountryCode CHAR(2) NOT NULL
)
CREATE TABLE Hotels
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(30) NOT NULL,
CityId INT FOREIGN KEY REFERENCES Cities(Id) NOT NULL,
EmployeeCount INT NOT NULL,
BaseRate DECIMAL(10,2)
)
CREATE TABLE Rooms
(
Id INT PRIMARY KEY IDENTITY,
Price DECIMAL(10,2) NOT NULL,
Type NVARCHAR(20) NOT NULL,
Beds INT NOT NULL,
HotelId INT FOREIGN KEY REFERENCES Hotels(Id) NOT NULL
)
CREATE TABLE Trips
(
Id INT PRIMARY KEY IDENTITY,
RoomId INT FOREIGN KEY REFERENCES Rooms(Id) NOT NULL,
BookDate DATE NOT NULL, CHECK(BookDate<ArrivalDate),
ArrivalDate DATE NOT NULL, CHECK(ArrivalDate<ReturnDate),
ReturnDate DATE NOT NULL,
CancelDate DATE
)
CREATE TABLE Accounts
(
Id INT PRIMARY KEY IDENTITY,
FirstName NVARCHAR(50) NOT NULL,
MiddleName NVARCHAR(20),
LastName NVARCHAR(50) NOT NULL,
CityId INT NOT NULL,
BirthDate DATE NOT NULL,
Email VARCHAR(100) UNIQUE NOT NULL
CONSTRAINT FK_CityId FOREIGN KEY (CityId)
REFERENCES Cities(Id)
)
CREATE TABLE AccountsTrips
(
AccountId INT FOREIGN KEY REFERENCES Accounts(Id) NOT NULL,
TripId INT FOREIGN KEY REFERENCES Trips(Id) NOT NULL,
Luggage INT NOT NULL, CHECK(Luggage >= 0)
)
You want to pick the longest and shortest trips per account from your data. As all you want to get from the trips is the duration, you can simply aggregate and show MIN and MAX duration:
SELECT
a.Id AS AccountId,
a.FirstName + ' ' + a.LastName AS [FullName],
MIN(DATEDIFF(day, T.ArrivalDate, T.ReturnDate)) AS LongestTrip,
MAXD(ATEDIFF(day, T.ArrivalDate, T.ReturnDate)) AS ShortestTrip
FROM
Accounts a
JOIN
AccountsTrips at ON a.Id = AT.AccountId
JOIN
Trips t ON T.Id = AT.TripId
WHERE
a.MiddleName IS NULL AND t.CancelDate IS NULL
GROUP BY
a.Id, a.FirstName, a.LastName
ORDER BY
LongestTrip DESC, ShortestTrip ASC;
If you wanted to show additional data from the trips, you would use window functions (probably MIN OVER and MAX OVER) and would then either show two rows per account or aggregate these two rows.
Related
assuming these 3 tables
create table item(
item_id integer NOT NULL primary key,
name varchar(50) NOT NULL,
description varchar(150) NOT NULL,
in_stock integer NOT NULL
)
create table customer(
customer_id VARCHAR(9) NOT NULL primary key,
name VARCHAR(50) NOT NULL,
lastname VARCHAR(50) NOT NULL,
phone VARCHAR(15) NOT NULL,
join_date DATE NOT NULL
)
create table purchase(
purchase_id integer references item,
customer_id varchar(9) references customer,
purchase_date TIMESTAMP NOT NULL,
amount INTEGER NOT NULL,
PRIMARY KEY(purchase_id, customer_id, purchase_date)
)
how could I get each unique name and the total amount of items purchased?
how could I get each purchase name and the buyer's name and lastname?
how could I get each item and how many of it were sold?
The two topics you are looking to learn are how to use GROUP BY and how to JOIN tables. Here's an example (more or less) that answers your first question and uses both tools:
select
C.customer_id as customer_id,
max(C.name) as customer_name,
sum(amount) as total_amount
from customer C
left join purchase P on C.customer_id = P.customer_id
group by C.customer_id
I am new to the SQL. I am learning joins in query so that i eterive the information from the table using information. I am working in this question .
Get the EmployeeNumber for the employees and the date they started any given department.
Below is my table definition :
CREATE TABLE Employees (
EmployeeID int IDENTITY(1,1) PRIMARY KEY
,EmployeeNumber int UNIQUE
,DateOfBirth datetime NOT NULL
,FirstName nvarchar(14) NOT NULL
,MiddleName nvarchar(14) NOT NULL
,LastName nvarchar(16) NOT NULL
,DateHired datetime NOT NULL
)
CREATE TABLE Customers (
CustomerID int IDENTITY(1,1) PRIMARY KEY
,FirstName nvarchar(14) NOT NULL
,MiddleName nvarchar(14) NOT NULL
,LastName nvarchar(16) NOT NULL
,DateLastVisited datetime NOT NULL
,EmailAddress nvarchar(52) NOT NULL
)
CREATE TABLE Departments (
DepartmentID int IDENTITY(1,1) PRIMARY KEY
,Code nchar(4) UNIQUE
,Name nvarchar(40) NOT NULL
)
CREATE TABLE DepartmentEmployees (
DepartmentEmployeeID int IDENTITY(1,1) PRIMARY KEY
,EmployeeID int NOT NULL
CONSTRAINT Department_Employee REFERENCES Employees(EmployeeID)
,DepartmentID int NOT NULL
CONSTRAINT Employee_Department REFERENCES Departments(DepartmentID)
,DateStarted datetime NOT NULL
,DateEnded datetime NOT NULL
)
CREATE TABLE Salaries (
SalaryID int IDENTITY(1,1) PRIMARY KEY
,EmployeeID int NOT NULL
CONSTRAINT Salaried_Employee REFERENCES Employees(EmployeeID)
,Amount money NOT NULL
,DateStarts datetime NOT NULL
,DateEnds datetime NOT NULL
)
I have added the information by inserting the data accordingly to the table.
For the question .
I have written this answer but i am not sure wether it is right or not.
SELECT e.EmployeeNumber,
d.DateStarted
FROM Employees e
Right
Join DepartmentEmployees d
on e.EmployeeID= d.DepartmentEmployeeID;
DepartmentEmployeeID is the primary key for the table department, you need to join the employee id's in both tables.
SELECT E.EmployeeNumber, D.DateStarted
FROM DepartmentEmployees D
LEFT JOIN Employees E
ON E.EmployeeID= D.EmployeeID;
i Need help in these tables, i want SQL statement to give me this :
the players who played in half or more of the games, lets assume that we have 6 different games in 'GameType' table ... So I want to display all players who played 3 or more games.
like :
ID surName number of games played
1 test1 3
2 test2 4
3 test3 3
4 test4 6
this what i done until now:
SELECT dbo.Player.ID, dbo.Player.surName, count(DISTINCT
dbo.PlayerInAGame.gameTypeName) AS games_played, count(DISTINCT
dbo.Game.gameTypeName) AS games_count
FROM dbo.Player INNER JOIN
dbo.PlayerInAGame ON dbo.Player.ID =
dbo.PlayerInAGame.playerID INNER JOIN
dbo.Game ON dbo.PlayerInAGame.gameTypeName = dbo.Game.gameTypeName AND
dbo.PlayerInAGame.gameDateTime = dbo.Game.gameStartDateTime
GROUP BY dbo.Player.ID, dbo.Player.surName, dbo.Game.DealerInGame
here is the tables:
create table Dealer
(
number int identity(1000,1) primary key,
firstName nvarchar(20) not null,
surName nvarchar(20) not null,
birthDate date not null,
startWorkingDate date not null,
ID char(9) check(ID like replicate('[0-9]',9)) not null unique,
check(datediff(year,birthDate,startWorkingDate)>=24)
)
create table GameType
(
name nvarchar(20) primary key,
description nvarchar(20) not null,
minimumPlayers tinyint check (minimumPlayers > 0) not null,
maximumPlayers tinyint check (maximumPlayers > 0) not null,
check(minimumPlayers <= maximumPlayers)
)
create table Game
(
gameTypeName nvarchar(20) references GameType(name) on delete cascade,
gameStartDateTime datetime,
gameEndTime time,
DealerInGame int not null references Dealer(number),
primary key(gameTypeName,gameStartDateTime)
)
create table Player
(
ID char(9) primary key,
firstName nvarchar(20) not null,
surName nvarchar(20) not null,
city nvarchar(20) not null,
birthDate date check(datediff(year,birthDate,getdate())>=18) not null,
preferred nvarchar(20) references GameType(name) on delete set null
)
create table PlayerInAGame
(
playerID char(9) references Player(ID),
gameTypeName nvarchar(20),
gameDateTime datetime,
betAmount int check(betAmount>0) not null,
winLosAmount int,
check((winLosAmount = -betAmount) or (winLosAmount>=betAmount)),
foreign key(gameTypeName,gameDateTime) references
Game(gameTypeName,gameStartDateTime), primary
key(playerID,gameTypeName,gameDateTime) )
create table PlayerDealerRelation
(
dealerNumber int references Dealer(number) on delete cascade,
playerID char(9) references Player(ID),
relationType char(1) check(relationType in ('P','G','B','C','U','N')),
primary key(dealerNumber,playerID)
)
If your query in the question gives you the correct count, then it is very easy to add an extra filter that would leave only those rows where games_played is more than half of games_count.
Just add HAVING:
SELECT
dbo.Player.ID,
dbo.Player.surName,
count(DISTINCT dbo.PlayerInAGame.gameTypeName) AS games_played,
count(DISTINCT dbo.Game.gameTypeName) AS games_count
FROM
dbo.Player
INNER JOIN dbo.PlayerInAGame ON dbo.Player.ID = dbo.PlayerInAGame.playerID
INNER JOIN dbo.Game
ON dbo.PlayerInAGame.gameTypeName = dbo.Game.gameTypeName
AND dbo.PlayerInAGame.gameDateTime = dbo.Game.gameStartDateTime
GROUP BY dbo.Player.ID, dbo.Player.surName, dbo.Game.DealerInGame
HAVING
count(DISTINCT dbo.PlayerInAGame.gameTypeName) >
count(DISTINCT dbo.Game.gameTypeName) / 2
I am building a chat site and for presenting the chats to the audiences, I have 3 Dropdownlists - Sports (Default is All Sports), Day/Month/Year, Users online/Total Users.
Now, if by default all sports is selected and I pick 1 month and Total users, the expected result should be
Chatroom name Total Users Online users
Basketball
Roomname27 32 5
Roomname11 15 3
Roomname32 8 1
Football
Roomname5 63 12
Roomname18 44 7
Roomname4 15 2
My query is
SELECT DISTINCT roo.[Sports],
roo.[Name],
COUNT(DISTINCT chu.ChatUserLogId) AS TotalUsers,
COUNT(DISTINCT liu.[LoggedInUserID]) AS UserOnline
FROM Room AS roo
LEFT JOIN LoggedInUser AS liu ON roo.RoomID = liu.RoomID
LEFT JOIN ChatUserLog AS chu ON roo.RoomID = chu.RoomID
AND chu.LoggedInTime >= DATEADD(DAY,-30,GETDATE())
GROUP BY roo.[Sports], roo.[Name]
ORDER BY TotalUsers DESC
And the table and their columns are as follows
CREATE TABLE [dbo].[Room] (
[RoomID] INT IDENTITY (6666, 1) NOT NULL,
[Name] VARCHAR (100) NOT NULL,
[Sports] VARCHAR (50) NOT NULL,
[CreatedDate] DATETIME DEFAULT (getdate()) NOT NULL,
[CreatedBy] VARCHAR (50) NOT NULL,
[CreatedUserID] INT NOT NULL,
PRIMARY KEY CLUSTERED ([RoomID] ASC)
);
CREATE TABLE [dbo].[ChatUserLog] (
[ChatUserLogId] BIGINT IDENTITY (1, 1) NOT NULL,
[MId] INT NOT NULL,
[RoomId] INT NOT NULL,
[LoggedInTime] DATETIME DEFAULT (getdate()) NOT NULL,
[LogOutTime] DATETIME DEFAULT (getdate()) NULL,
PRIMARY KEY CLUSTERED ([ChatUserLogId] ASC)
);
CREATE TABLE [dbo].[LoggedInUser] (
[LoggedInUserID] INT IDENTITY (1, 1) NOT NULL,
[MId] INT NOT NULL,
[RoomID] INT NOT NULL,
[NickName] VARCHAR (50) NOT NULL,
[Icon] VARCHAR (MAX) NOT NULL,
CONSTRAINT [PK_LoggedInUser] PRIMARY KEY CLUSTERED ([LoggedInUserID] ASC)
);
For this above query, say, if I have 7 chatoom topics in Basketball, I get Basketball's any 3 rooms shown & the whole Basketball is repeated 7 times (Not sorted properly to my expectation too) and similary, if I have 15 chatroom topics in Football, I get whole Football repeated 15 times without getting sorted properly too.
What are the mistakes, I have done here? Thanks in advance and have a nice day ahead.
Well with your method you are actually multiplying the row because of the two joins.
So you need to aggregate first, then join.
So in the end :
with agg_ChatUserLog as (
select RoomId, count(*) as cnt_user_tot
from ChatUserLog
group by RoomId),
agg_LoggedInUser as (
select RoomId, count(*) as cnt_user_logged
from LoggedInUser
group by RoomId)
select name, cnt_user_tot, cnt_user_logged
from Room r
left outer join agg_ChatUserLog acu on acu.RoomId = r.RoomId
left outer join agg_LoggedInUser alu on alu.RoomId = r.RoomId
Learning, be kind.
I am trying to understand how this works and I have done several successful conversions, but this one I am stumped on.
How do I take this code and convert it to a subquery? I'm a little lost.
SELECT o.FirstName + ' ' + o.LastName AS Driver, COUNT(DISTINCT s.vehicleID) NoOfBusesUsed
FROM Operators AS o, Runs AS r, Schedules AS s JOIN Trips AS t
ON s.scheduleID = t.scheduleID
WHERE r.BidDate BETWEEN '09/01/2004' AND '09/30/2004'
GROUP BY o.FirstName + ' ' + o.LastName
HAVING COUNT(s.vehicleID) > 1
Here is how my tables are setup. If more info is needed, I can post.
CREATE TABLE Operators
(
SeniorityNumber char(4) NOT NULL
CONSTRAINT ck_Operators_Seniority
CHECK (SeniorityNumber LIKE '[0-9][0-9][0-9][0-9]'),
FirstName varchar(25) NOT NULL,
LastName varchar(35) NOT NULL,
HireDate smalldatetime
CONSTRAINT ck_Operators_HireDate CHECK (HireDate <=Getdate())
)
CREATE TABLE Trips
(
RouteNumber varchar(4) NOT NULL,
StartLocation varchar(50) NOT NULL,
StartTime time NOT NULL,
EndLocation varchar(50) NOT NULL,
EndTime time NOT NULL,
EffectiveDate smalldatetime NOT NULL
CHECK (EffectiveDate >= cast('1/1/2000' as smalldatetime)),
CONSTRAINT ck_Trips_StartEnd CHECK (EndTime > StartTime)
)
CREATE TABLE Vehicles
(
Manufacturer varchar(50)
DEFAULT 'Gillig',
Model varchar(50),
ModelYear int
DEFAULT DatePart(yyyy,GetDate())
CHECK (ModelYear <= DatePart(yyyy,GetDate())),
PurchaseDate smalldatetime
)
GO
ALTER TABLE operators
ADD OperatorID int IDENTITY --Primary Key
GO
ALTER TABLE Operators
ADD CONSTRAINT pkOperators Primary key (OperatorID)
ALTER TABLE Vehicles
ADD VehicleID int IDENTITY Primary Key
ALTER TABLE Trips
ADD TripID int IDENTITY Primary key
GO
CREATE TABLE Runs
(
RunID int IDENTITY NOT NULL Primary Key,
OperatorID int NOT NULL REFERENCES Operators,
BidDate date NOT NULL
CONSTRAINT ckRunBidDate CHECK
(biddate <= dateadd(mm,6,getdate())) --getdate() + 180
)
GO
CREATE TABLE Schedules
(
ScheduleID int IDENTITY Primary Key,
RunID int NOT NULL,
VehicleID int NOT NULL,
CONSTRAINT fk_Schedules_Runs FOREIGN KEY (RunID)
REFERENCES Runs(RunID),
CONSTRAINT fk_Schedules_Vehicles FOREIGN KEY (VehicleID)
REFERENCES Vehicles
)
ALTER TABLE Trips
ADD ScheduleID int NULL REFERENCES Schedules
When you want to use a query as a sub-query you can use WITH statement or a derived table like:
With:
;WITH subQuery AS (
/* Your query here */
)
SELECT *
FROM subQuery
Derived table
SELECT *
FROM (
/* your query here */
) As subQuery
I think you should use a query like this:
SELECT
o.FirstName + ' ' + o.LastName AS Driver,
DT.cnt AS NoOfBusesUsed
FROM
Operators AS o
JOIN
(SELECT
r.OperatorID,
COUNT(DISTINCT s.VehicleID) AS cnt
FROM
Schedules s
JOIN
Runs r ON s.RunID = r.RunID
) AS DT
ON DT.OperatorID = o.OperatorID
WHERE
ISNULL(DT.cnt, 0) > 1