Display city with second highest number of stores.
here is table toy_store with data IN IMAGETOY_STORE
Remember this is not service to complete your assignments, you should try it first, show some efforts, for now you could get ans for you question and there are number of way to do this.
SELECT TOP(1),*
FROM
(
SELECT TOP(2) CITY,COUNT(CITY)
FROM TableName
GROUP BY CITY
ORDER BY CITY DESC
)M
The question as I and #jaydip-jadhav have mentioned lacks details. It's also very old at this point but since it came back up via your comments I decided to take another look.
However, the above should work with minimal changes depending on what you're using (again, more details would help such as what DBMS your using and what version, etc).
That said you could also google what you're after and find a variety of solutions.
An Example solution
But here's 2 working basic examples you can view, run and use with this SQL Fiddle.
If the fiddle stops working here's the details you could use to recreate on your own somewhere.
This is using MySQL 5.6 (old, but so's this question).
Schema based on your image (next time, type it out):
CREATE TABLE IF NOT EXISTS `toy_store` (
`toy_store_id` int(6) NOT NULL,
`toy_store_name` varchar(200) NOT NULL,
`city` varchar(200) NOT NULL,
`phone_number` varchar(200) NOT NULL,
`store_opening_time` varchar(200) NOT NULL,
`store_closing_time` varchar(200) NOT NULL,
PRIMARY KEY (`toy_store_id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `toy_store` (`toy_store_id`, `toy_store_name`, `city`, `phone_number`, `store_opening_time`, `store_closing_time`) VALUES
('1', 'kids cave', 'Delhi', '9912312312', '2014-04-01 09:10:12', '2014-04-01 21:42:05'),
('2', 'kids corner', 'Mumbai', '9912312312', '2014-04-01 09:10:12', '2014-04-01 21:42:05'),
('3', 'play and grow', 'Mumbai', '9912312312', '2014-04-01 09:10:12', '2014-04-01 21:42:05'),
('4', 'puzzles and more', 'Delhi', '9912312312', '2014-04-01 09:10:12', '2014-04-01 21:42:05'),
('5', 'uncle same toys den', 'Delhi', '9912312312', '2014-04-01 09:10:12', '2014-04-01 21:42:05'),
('6', 'mickey toys', 'Delhi', '9912312312', '2014-04-01 09:10:12', '2014-04-01 21:42:05'),
('7', 'mickey toys', 'Somewhere Else', '9912312312', '2014-04-01 09:10:12', '2014-04-01 21:42:05');
2 basic queries that work against the above schema:
SELECT * FROM (
SELECT city, count(city) as count_city
FROM toy_store
GROUP BY city
ORDER BY COUNT(city) desc
LIMIT 2
) as top2
ORDER BY top2.count_city asc
LIMIT 1;
-- RESULT
-- city count_city
-- Mumbai 2
SELECT DISTINCT city, count(city) as count_city
FROM toy_store
GROUP BY city
ORDER BY COUNT(city)
LIMIT 1,1;
-- RESULT
-- city count_city
-- Mumbai 2
Related
My dataset has 2 tables:
animals with animal_id and animal_type
owners with animal_id and owner_name
I want to get records only for those animals (+ their owners name) which owners have a CAT and another different pet.
Here is my schema:
CREATE TABLE IF NOT EXISTS `animals` (
`animal_id` int(6) unsigned NOT NULL,
`animal_type` varchar(200) NOT NULL,
PRIMARY KEY (`animal_id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `animals` (`animal_id`, `animal_type`) VALUES
('1', 'cat'),
('2', 'dog'),
('3', 'cat'),
('4', 'cat'),
('5', 'dog'),
('6', 'dog'),
('7', 'cat'),
('8', 'dog'),
('9', 'cat'),
('10', 'hamster');
CREATE TABLE IF NOT EXISTS `owners` (
`animal_id` int(6) unsigned NOT NULL,
`owner_name` varchar(200) NOT NULL,
PRIMARY KEY (`animal_id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `owners` (`animal_id`, `owner_name`) VALUES
('1', 'CatOwner'),
('2', 'DogOwner'),
('3', 'CatsOwner'),
('4', 'CatsOwner'),
('5', 'DogsOwner'),
('6', 'DogsOwner'),
('7', 'CatDogOwner'),
('8', 'CatDogOwner'),
('9', 'CatHamsterOwner'),
('10', 'CatHamsterOwner');
I can filter and show only records for owners which have more then one pet:
SELECT *
FROM animals AS a
JOIN owners AS o
ON a.animal_id = o.animal_id
WHERE o.owner_name IN (SELECT o.owner_name
FROM animals AS a
JOIN owners AS o
ON a.animal_id = o.animal_id
GROUP BY o.owner_name HAVING COUNT(o.owner_name) > 1)
Please tell me how can I make it this way:
I would suggest window functions:
SELECT ao.*
FROM (SELECT a.*, o.owner_name,
SUM(CASE WHEN a.animal_type = 'cat' THEN 1 ELSE 0 END) OVER (PARTITION BY o.owner_name) as num_cats,
COUNT(*) OVER (PARTITION BY o.owner_name) as num_animals
FROM owners o JOIN
animals a
ON a.animal_id = o.animal_id
) ao
WHERE num_cats > 0 AND num_animals >= 2;
Note: I'm not clear if the condition is for more than one animal or an animal that is not a cat. If the latter, then use:
SELECT ao.*
FROM (SELECT a.*, o.owner_name,
SUM(CASE WHEN a.animal_type = 'cat' THEN 1 ELSE 0 END) OVER (PARTITION BY o.owner_name) as num_cats,
COUNT(*) OVER (PARTITION BY o.owner_name) as num_animals
FROM owners o JOIN
animals a
ON a.animal_id = o.animal_id
) ao
WHERE num_cats > 0 AND num_animals <> num_cats;
I work with languages where I can assign intermediate outputs to a variable and then work the with variables to create a final output. I know SQL doesn't work this way as much. Currently I have queries that require me to make subsets of tables and then I want to join those subsets together. I can mimic the variable assignment I do in my native languages using a VIEW but I want to know how to do this using a single query (otherwise the database will get messy with views quickly).
Below is a MWE to make 2 initial tables DeleteMe1 and DeleteMe2 (at the end). Then I'd use these two views to get current snapshots of each table. Last I'd use LEFT JOIN with the views to merge the 2 data sets.
Is there a way to see the code SQL uses on the Join Snapshoted Views header code I supply below
How could I eliminate the views intermediate step and combine into a single SQL query?
Create views for current snapshot:
CREATE VIEW [dbo].[CurrentSnapshotDeleteMe1]
AS
SELECT DISTINCT *
FROM
(SELECT
t.[Id]
,t.[OppId]
,t.[LastModifiedDate]
,t.[Stage]
FROM
[dbo].DeleteMe1 as t
INNER JOIN
(SELECT
[OppId], MAX([LastModifiedDate]) AS MaxLastModifiedDate
FROM
[dbo].DeleteMe1
WHERE
LastModifiedDate <= GETDATE()
GROUP BY
[OppId]) AS referenceGroup ON t.[OppId] = referenceGroup.[OppId]
AND t.[LastModifiedDate] = referenceGroup.[MaxLastModifiedDate]) as BigGroup
GO
CREATE VIEW [dbo].[CurrentSnapshotDeleteMe2]
AS
SELECT DISTINCT *
FROM
(SELECT
t.[Id]
,t.[OppId]
,t.[LastModifiedDate]
,t.[State]
FROM
[dbo].DeleteMe2 AS t
INNER JOIN (
SELECT [OppId], MAX([LastModifiedDate]) AS MaxLastModifiedDate
FROM [dbo].DeleteMe2
WHERE LastModifiedDate <= GETDATE()
GROUP BY [OppId]
) as referenceGroup
ON t.[OppId] = referenceGroup.[OppId] AND t.[LastModifiedDate] = referenceGroup.[MaxLastModifiedDate]
) as BigGroup
GO
Join snapshoted views:
SELECT
dm1.[Id] as IdDM1
,dm1.[OppId]
,dm1.[LastModifiedDate] as LastModifiedDateDM1
,dm1.[Stage]
,dm2.[Id] as IdDM2
,dm2.[LastModifiedDate] as LastModifiedDateDM2
,dm2.[State]
FROM [dbo].[CurrentSnapshotDeleteMe1] as dm1
LEFT JOIN [dbo].[CurrentSnapshotDeleteMe2] as dm2 ON dm1.OppId = dm2.OppId
Create original tables:
CREATE TABLE DeleteMe1
(
[Id] INT,
[OppId] INT,
[LastModifiedDate] DATE,
[Stage] VARCHAR(250),
)
INSERT INTO DeleteMe1
VALUES ('1', '1', '2019-04-01', 'A'),
('2', '1', '2019-05-01', 'E'),
('3', '1', '2019-06-01', 'B'),
('4', '2', '2019-07-01', 'A'),
('5', '2', '2019-08-01', 'B'),
('6', '3', '2019-09-01', 'C'),
('7', '4', '2019-10-01', 'B'),
('8', '4', '2019-11-01', 'C')
CREATE TABLE DeleteMe2
(
[Id] INT,
[OppId] INT,
[LastModifiedDate] DATE,
[State] VARCHAR(250),
)
INSERT INTO DeleteMe2
VALUES (' 1', '1', '2018-07-01', 'California'),
(' 2', '1', '2017-11-01', 'Delaware'),
(' 3', '4', '2017-12-01', 'California'),
(' 4', '2', '2018-01-01', 'Alaska'),
(' 5', '4', '2018-02-01', 'Delaware'),
(' 6', '2', '2018-09-01', 'Delaware'),
(' 7', '3', '2018-04-01', 'Alaska'),
(' 8', '1', '2018-05-01', 'Hawaii'),
(' 9', '4', '2018-06-01', 'California'),
('10', '1', '2018-07-01', 'Connecticut'),
('11', '2', '2018-08-01', 'Delaware'),
('12', '2', '2018-09-01', 'California')
I work with languages where I can assign intermediate outputs to a variable and then work the with variables to create a final output. I know SQL doesn't work this way as much.
Well, that's not true, sql does work this way, or at least sql-server does. You have temp tables and table variables.
Although you named your tables DeleteMe, from your statements it seems like it's the views you wish to treat as variables. So I'll focus on this.
Here's how to do it for your first view. It puts the results into a temporary table called #tempData1:
-- Optional: In case you re-run before you close your connection
if object_id('tempdb..#snapshot') is not null
drop table #snapshot1;
select
distinct t.Id, t.OppId, t.LastModifiedDate, t.Stage
into #snapshot1
from dbo.DeleteMe1 as t
inner join (
select OppId, max(LastModifiedDate) AS MaxLastModifiedDate
from dbo.DeleteMe1
where LastModifiedDate <= getdate()
group by OppId
) referenceGroup
on t.OppId = referenceGroup.OppId
and t.LastModifiedDate = referenceGroup.MaxLastModifiedDate;
The hashtag tells sql server that the table is to be stored temporarially. #tempTable1 will not survive when your connection closes.
Alternatively, you can create a table variable.
declare #snapshot1 table (
id int,
oppId int,
lastModifiedDate date,
stage varchar(50)
);
insert #snapshot1 (id, oppId, lastModifiedDate, stage)
select distinct ...
This table is discarded as soon as the query has finished executing.
From there, you can join on your temp tables:
SELECT dm1.[Id] as IdDM1, dm1.[OppId],
dm1.[LastModifiedDate] as LastModifiedDateDM1, dm1.[Stage],
dm2.[Id] as IdDM2, dm2.[LastModifiedDate] as LastModifiedDateDM2,
dm2.[State]
FROM #snapshot1 dm1
LEFT JOIN #snapshot2 dm2 ON dm1.OppId = dm2.OppId
Or your table variables:
From there, you can join on your temp tables:
SELECT dm1.[Id] as IdDM1, dm1.[OppId],
dm1.[LastModifiedDate] as LastModifiedDateDM1, dm1.[Stage],
dm2.[Id] as IdDM2, dm2.[LastModifiedDate] as LastModifiedDateDM2,
dm2.[State]
FROM #snapshot1 dm1
LEFT JOIN #snapshot2 dm2 ON dm1.OppId = dm2.OppId
This is my first time asking a SQL related question. I am having a difficult time getting this query to work.
Basically, I have a database that has 3 tables Course, Faculty and Adjunct. This query is supposed to create a view named Top3Enrollment that returns FirstName, LastName, TotalStudents, and MaxEnrollment of the 3 faculty members with the largest total enrollment for their courses, along with the highest enrollment among the classes they teach.
When attempting to write the query I get an error with selecting the column FirstName
My query:
CREATE VIEW Top3Enrollment
AS
SELECT TOP 3 PERCENT
FirstName, LastName, SUM(Enrollment), MAX(Enrollment)
FROM
Faculty
JOIN
Course ON Faculty.Faculty_ID = Course.Faculty_ID
ORDER BY
MAX(Enrollment);
The error I get is:
Msg 8120, Level 16, State 1, Procedure Top3Enrollment, Line 3 [Batch Start Line 0]
Column 'Faculty.FirstName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
My database structures:
CREATE TABLE Faculty
(
Faculty_ID VARCHAR(2),
LastName VARCHAR(20),
FirstName VARCHAR(20),
Department VARCHAR(10),
Campus VARCHAR(10)
);
INSERT INTO Faculty
VALUES ('1', 'Brown', 'Joe', 'Business', 'Kent'),
('2', 'Smith', 'John', 'Economics', 'Kent'),
('3', 'Jones', 'Sally', 'English', 'South'),
('4', 'Black', 'Bill', 'Economics', 'Deerwood'),
('5', 'Green', 'Gene', 'Business', 'South');
CREATE TABLE Course
(
Course_ID CHAR(2),
Ref_Number CHAR(5),
Faculty_ID VARCHAR(2),
Term Char(1),
BegDate SMALLDATETIME,
Enrollment INTEGER,
TotRev FLOAT
);
INSERT INTO Course
VALUES ('1', '12345', 'a', 'A', '2016-01-08 00:00:00', 24, 12345.32 ),
('2', '54321', '3', 'B', '2016-02-04 00:00:00', 18, 21435.51 ),
('3', '13524', '1', 'B', '2016-02-04 00:00:00', 7, 1256.67 ),
('4', '24653', '1', 'C', '2016-03-04 00:00:00', 29, 54421.11 ),
('5', '98765', '5', 'A', '2016-01-08 00:00:00', 35, 246753.23),
('6', '14862', '2', 'B', '2016-02-04 00:00:00', 14, 9876.87),
('7', '96032', '1', 'C', '2016-03-04 00:00:00', 8, 863159.31),
('8', '81256', '5', 'A', '2016-01-08 00:00:00', 5, 98762.14),
('9', '64321', '2', 'C', '2016-03-04 00:00:00', 23, 2965.98),
('10','90908', 'a', 'A', '2016-01-08 00:00:00', 45, 91724.02),
('11','90908', '3', 'A', '2016-01-08 00:00:00', 23, 73725.77),
('12','90908', '3', 'A', '2016-01-08 00:00:00', 16, 84224.29),
('13','90908', 'b', 'A', '2016-01-08 00:00:00', 13, 42719.82);
CREATE TABLE Adjuncts
(
Faculty_ID Char(2),
LastName VARCHAR(20),
FirstName VARCHAR(20),
Department VARCHAR(10),
Campus VARCHAR(10)
);
INSERT INTO Adjuncts
VALUES ('a', 'Rogers', 'Aaron', 'Business', 'Kent'),
('b', 'Manning', 'Peyton', 'Economics', 'North'),
('c', 'Drew', 'Maurice', 'English', 'Cecil'),
('d', 'Griffin', 'Robert', 'Music', 'Deerwood'),
('e', 'Goodell', 'Roger', 'Economics', 'South'),
('f', 'Vilma', 'Jonathan', 'Business', 'Kent');
Note:
I Understand I cannot have Order By but I wouldn't know what else to use
Added the database code
When you use aggregate functions like sum and max together with other columns you need to group your aggregations by those other columns.
Add GROUP BY like this
SELECT TOP 3 PERCENT FirstName, LastName, SUM(Enrollment), MAX(Enrollment)
FROM Faculty
JOIN Course ON Faculty.Faculty_ID = Course.Faculty_ID
GROUP BY FirstName, LastName
ORDER BY MAX(Enrollment);
CREATE TABLE STORE
(
STORE_CODE INT,
STORE_NAME VARCHAR(20),
STORE_YTD_SALES NUMERIC,
REGION_CODE INT,
EMP_CODE INT
);
INSERT INTO STORE
VALUES ('1', 'Access Junction', '1003455.76', '2', '8'),
('2', 'Database Corner', '1421987.39', '2', '12'),
('3', 'Tuple Charge', '986783.22', '1', '7'),
('4', 'Attribute Alley', '944568.56', '2', '3'),
('5', 'Primary Key Point', '2930098.45', '1', '15');
CREATE TABLE REGION
(
REGION_CODE INT,
REGION_DESCRIPT VARCHAR(10)
);
INSERT INTO REGION
VALUES ('1', 'East'), ('2', 'West');
I am new to SQL I need to make a list of all stores and regions, as in the following sample:
Code Description
----------- --------------------
1 Access Junction
1 East
2 Database Corner
but I am not sure how to make it work. Can someone help me, please?
Solution for your problem:
SELECT Code, Description
FROM (
SELECT STORE_CODE AS Code, Store_Name AS Description
FROM Store
UNION ALL
SELECT REGION_CODE AS Code, REGION_DESCRIPT AS Description
FROM REGION
) AS t
ORDER BY Code,Description
OUTPUT:
Code Description
---------------------------
1 Access Junction
1 East
2 Database Corner
2 West
3 Tuple Charge
4 Attribute Alley
5 Primary Key Point
Link To the Demo:
http://sqlfiddle.com/#!18/6cc1a/2
I'm working with a course catalog table in which I have catalog codes and course codes for when the courses were offered. What I need to do is to determine when a course isn't being offered any longer and mark it as an archived course.
CREATE TABLE [dbo].[COURSECATALOG](
[catalog_code] [char](6) NOT NULL,
[course_code] [char](7) NOT NULL,
[title] [char](40) NOT NULL,
[credits] [decimal](7, 4) NULL,
)
insert into coursecatalog
values
('200810', 'BIOL101', 'Biology', '3'),
('200810', 'CHEM201', 'Advanced Chemistry', '3'),
('200810', 'ACCT101', 'Beginning Accounting', '3'),
('201012', 'ACCT101', 'Beginning Accounting', '3'),
('201214', 'ACCT101', 'Beginning Accounting', '3'),
('201214', 'ENGL101', 'English Composition', '3'),
('201416', 'PSYC101', 'Psychology', '3'),
('201618', 'PSYC101', 'Psychology', '3'),
('201618', 'BIOL101', 'Biology', '3'),
('201618', 'CHEM201', 'Advanced Chemistry', '3'),
('201618', 'ENGL101', 'English Composition', '3'),
('201618', 'PSYC101', 'Psychology', '3')
In this case, I need to return ACCT101 - Beginning Accounting since this isn't being offered anymore and should be considered an archived course.
My code so far:
SELECT
catalog_code, course_code
FROM COURSECATALOG t1
WHERE NOT EXISTS (SELECT 1
FROM COURSECATALOG t2
WHERE t2.catalog_code <> t1.catalog_code
AND t2.course_code = t1.course_code)
order by
course_code, catalog_code
But this only returns courses that were only ever offered one time (in one catalog). I need to figure out how I can get courses that might have been offered in multiple catalogs but isn't offered any longer.
Any assistance that can be provide is appreciated!
Thank you!
I think the catalog_code is a date with YYYYMM format
SELECT course_code FROM (
SELECT CONVERT(char, catalog_code,112) AS catalog_code, course_code FROM COURSECATALOG
) AS Q
GROUP BY course_code
HAVING MAX(catalog_code) < '20160101'
Example:
http://sqlfiddle.com/#!6/32adfb/14/1
You want something like this:
SELECT course_code
FROM COURSECATALOG t1
GROUP BY course_code
HAVING MAX(catalog_code) <> '201618';
This assumes that "currently being offered" means that it is in the 201618 catalog.
You could calculate the most recent catalog:
SELECT course_code
FROM COURSECATALOG t1
GROUP BY course_code
HAVING MAX(catalog_code) <> (SELECT MAX(catalog_code FROM COURSECATALOG);