Significance of ORDER BY <particular multiple number> - mysql

Help me understand the following snippet:
...
ORDER BY 2, 12, 11

In SQL ORDER BY is the Keyword used to Order your Resultset based on the values of a Particular column or Columns either Ascending or Descending order.
The ORDER BY is Given as the Last Statement in a SELECT.
The Syntax is :
SELECT
<List of Columns>
FROM <Table Name>
<Filter Conditions > -- Optional
<Group By and Having> - Optional
ORDER BY
<Column 1> <ASC or DESC>,
<Column 2> <ASC or DESC>,
.......
<Column N> <ASC or DESC>,
You Can Either Give the Column Names or the Ordinal Position of the Column in the Select List.
For Example :
SELECT
EmpId,
FirstName,
LastName,
Age,
ContactNumber
FROM Employee
ORDER BY
FirstName,
Age
Can Also be written as
SELECT
EmpId,
FirstName,
LastName,
Age,
ContactNumber
FROM Employee
ORDER BY
2,4
in the second one, I'm giving the Ordinal position of Columns FirstName and Age instead of specifying the Column Name.
This approach is more useful when you have 2 columns with the Same Name in your Resultset.
Example :
SELECT
EmpId,
*
ContactNumber
FROM Employee
ORDER BY
EmpId
The above will give you the following error
Msg 209, Level 16, State 1, Line 5 Ambiguous column name 'EmpId'.
So Instead you can say
SELECT
EmpId,
*
ContactNumber
FROM Employee
ORDER BY
1

You can get and learn in details from the below query. Multiple column OrderBy is useful when similar values are present in table.
Create Table Orders (Id int, ProdName Varchar(20))
insert into Orders Values (1, 'A'), (4, 'C'), (2, 'B'), (3, 'E'), (4, 'G'), (5, 'D'), (6, 'F'), (7, 'G')
Select * from Orders
order by 1 -- Order By Id Ascending
Select * from Orders
order by 1 desc -- Order By Id Descending
Select * from Orders
order by 2 -- Order By Name Ascending
Select * from Orders
order by 2 desc -- Order By Name Descending
Select * from Orders
order by 1, 2 -- Order By Id first and then Name Ascending.
-- It will come same Id first and same name later
Select * from Orders
order by 1 asc, 2 desc --First priority of Id ascending then Name in descending order
Select * from Orders
order by 1, 2 desc
You can find the live demo Live Demo Here

Related

sql query question for most name in table with multiple most names

fbn table:
create table fbn (
id int,
name varchar(40),
birthday date,
gender varchar(10));
INSERT into fbn values
(1, "James", "2000-04-22", "male"),
(2, "Julia", "2006-02-27", "female"),
(3, "Ethan", "2013-05-23", "male"),
(4, "Lion", "2014-09-11", "male"),
(5, "Ethan", "2006-01-01", "male"),
(6, "Lion", "2006-02-01", "male");
what's the name that occur most? note that there are two names (Ethan and Lion) occur most often. I have two solutions as below:
select tmp2.name
from (select tmp.name,
dense_rank() over(order by tmp.name_count desc) rank
from (select name,
count(*) name_count
from fbn
group by name) tmp
) tmp2
where tmp2.rank = 1;
and the 2nd solution:
select name from fbn
group by name
having count(name) = (select count(name) from fbn
group by name
order by count(name) desc
limit 1);
both seem to be working, but both looks like too complicated. is there any other solution that's more concise easier to understand? Thanks
How about this:
SELECT counts,GROUP_CONCAT(NAME) AS names
FROM
(SELECT NAME, COUNT(*) counts FROM fbn GROUP BY NAME) A
GROUP BY counts
ORDER BY counts DESC
LIMIT 1;
Fiddle here : https://www.db-fiddle.com/f/qzmJAx5LFfzZdYyDetUfex/1
I think you can simply:
select count(id) as num_names, name from fbn group by name order by num_names desc limit 1;
For Ms :
select Top 1 count(id) as num_names, name from fbn group by name order by num_names desc
Disable ONLY_FULL_GROUP_BY if its enabled using:
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
Here in inner query provide name with occurrence count. And outer query just use that temporary table to get max count value. Now it will return single row with name & total occurrence(max).
SELECT name, MAX(occurrence)
FROM (SELECT name, COUNT(id) occurrence
FROM fbn
GROUP BY name) t;

Return ID value

I have a simple table arranged as below and I'd like to write a query that returns the single client_id that has most transactions. One client has most transactions than any other client in the table.
transaction_id int 
client_id int 
comments varchar 
Cheers.
Here is one method for obtaining the data by counting the rows, grouping on the client_id and then filtering for top 1 ordered by the count descending.
declare #table table (
transaction_id int,
client_id int,
comments varchar(20)
);
insert into #table (transaction_id, client_id, comments)
values
(1, 1, ''),
(2, 2, ''),
(3, 2, ''),
(4, 3, '')
select top 1 client_id, count(*) as vol
from #table
group by client_id
order by vol desc
This will do it for you:
SELECT client_id FROM table_name GROUP BY client_id ORDER BY COUNT(*) DESC limit 1;
select client_id, count(transaction_id)
from table
group by client_id
order by 2 desc
limit 1;
Group by helps to gather records based on a particular column and the countreturns the number of records corresponding to that column value. Order by desc arranges in descending order and limit 1 restricts to 1 record.

Selecting all rows with only one value in column with another common value

my table:
drop table if exists new_table;
create table if not exists new_table(
obj_type int(4),
user_id varchar(30),
payer_id varchar(30)
);
insert into new_table (obj_type, user_id, payer_id) values
(1, 'user1', 'payer1'),
(1, 'user2', 'payer1'),
(2, 'user3', 'payer1'),
(1, 'user1', 'payer2'),
(1, 'user2', 'payer2'),
(2, 'user3', 'payer2'),
(3, 'user1', 'payer3'),
(3, 'user2', 'payer3');
I am trying to select all the payer id's whose obj_type is only one value and not any other values. In other words, even though each payer has multiple users, I only want the payers who are only using one obj_type.
I have tried using a query like this:
select * from new_table
where obj_type = 1
group by payer_id;
But this returns rows whose payers also have other user's with other obj_types. I am trying to get a result that looks like:
obj | user | payer
----|-------|--------
3 | user1 | payer3
3 | user2 | payer3
Thanks in advance.
That is actually easy:
SELECT player_id
FROM new_table
GROUP BY player_id
HAVING COUNT(DISTINCT obj_type) = 1
Having filters rows just like WHERE but it does so after the aggregation.
The difference is best explained by an example:
SELECT dept_id, SUM(salary)
FROM employees
WHERE salary > 100000
GROUP BY dept_id
This will give you the sum of the salaries of people earning more than 100000 each.
SELECT dept_id, SUM(salary)
FROM employees
GROUP BY dept_id
HAVINF salary > 100000
The second query will give you the departments where all employees together earn more than 100000 even if no single employee earns that much.
If you want to return all rows without grouping them you can use analytic functions:
SELECT * FROM (
SELECT obj_type,user_id,
payer_id,
COUNT(DISTINCT obj_type) OVER (PARTITION BY payer_id) AS distinct_obj_type
FROM new_table)
WHERE distinct_obj_type = 1
Or you can use exist with the query above:
SELECT *
FROM new_table
WHERE payer_id IN (SELECT payer_id
FROM new_table
GROUP BY payer_id
HAVING COUNT(DISTINCT obj_type) = 1)

How come RAND() is messing up in SQL subquery?

My goal is to select a random business and then with that business' id get all of their advertisements. I am getting unexpected results from my query. The number of advertisement rows returned is always what I assume is the value of "SELECT id FROM Business ORDER BY RAND() LIMIT 1". I have 3 businesses and only 1 business that has advertisement rows (5 of them) yet it always displays between 1-3 of the 5 advertisements for the same business.
SELECT * FROM Advertisement WHERE business_id=(SELECT id FROM Business ORDER BY RAND() LIMIT 1) ORDER BY priority
Business TABLE:
Advertisement TABLE:
Data for Advertisement and Business tables:
INSERT INTO `Advertisement` (`id`, `business_id`, `image_url`, `link_url`, `priority`) VALUES
(1, 1, 'http://i64.tinypic.com/2w4ehqw.png', 'https://www.dennys.com/food/burgers-sandwiches/spicy-sriracha-burger/', 1),
(2, 1, 'http://i65.tinypic.com/zuk1w1.png', 'https://www.dennys.com/food/burgers-sandwiches/prime-rib-philly-melt/', 2),
(3, 1, 'http://i64.tinypic.com/8yul3t.png', 'https://www.dennys.com/food/burgers-sandwiches/cali-club-sandwich/', 3),
(4, 1, 'http://i64.tinypic.com/o8fj9e.png', 'https://www.dennys.com/food/burgers-sandwiches/bacon-slamburger/', 4),
(5, 1, 'http://i68.tinypic.com/mwyuiv.png', 'https://www.dennys.com/food/burgers-sandwiches/the-superbird/', 5);
INSERT INTO `Business` (`id`, `name`) VALUES
(1, 'Test Dennys'),
(2, 'Test Business 2'),
(3, 'Test Business 3');
You're assuming your query does something it doesn't do.
(SELECT id FROM Business ORDER BY RAND() LIMIT 1) isn't materialized at the beginning of the query. It's evaluated for each row... so for each row, we're testing whether that business_id matches the result of a newly-executed instance of the subquery. More thorough test data (more than one business included) should reveal this.
You need to materialize the result into a derived table, then join to it.
SELECT a.*
FROM Advertisement a
JOIN (
SELECT (SELECT id
FROM Business
ORDER BY RAND()
LIMIT 1) AS business_id
) b ON b.business_id = a.business_id;
The ( SELECT ... ) x construct creates a temporary table that exists only for the duration of the query and uses the alias x. Such tables can be joined just like real tables.
MySQL calls this a Subquery in the FROM Clause.
Try following query
SELECT * FROM Advertisement WHERE business_id = (select floor(1 + rand()* (select count(*) from Business)));
To retrieve rows in random order use SELECT * Instead Of Id and then query for its id.
SELECT * FROM Advertisement WHERE business_id=(SELECT ID FROM (SELECT * FROM Business ORDER BY RAND() LIMIT 1) as table1)
In this case with your example data, only when rand returns 1 you get results.

Order results in which it was read in. Using in()

This is my query in mysql:
SELECT school_id, first_name, last_name, email, blog_username, comment_username
FROM table
WHERE user_id IN (100, 3,72) ;
The results show the two user_id's in ascending order. How can I make it so that it is ordered by in which is was received?
So instead of 3, 72, 100 I want the results to be 100, 3, 72.
Select school_id, first_name, last_name, email, blog_username, comment_username
From table
Where user_id IN ( 100, 3, 72 )
Order By Case
When user_id = 100 Then 1
When user_id = 3 Then 2
When user_id = 72 Then 3
End Asc
Addition explanation:
What is being sought is the ability to order the rows in a custom manner. Said another way, we need to add custom cardinality to a set of values that do not conform to a standard cardinality. A Case expression can be used to do just that. Another way to accomplish the same thing would be:
Select school_id, first_name, last_name, email, blog_username, comment_username
From table
Join (
Select 100 As user_id, 1 As Sort
Union All Select 3, 2
Union All Select 72, 3
) As Seq
On Seq.user_id = table.user_id
Order By Seq.Sort
MySQL has a function FIELD() which is suited for this:
ORDER BY FIELD(user_id, 100, 3, 72 )
http://dev.mysql.com/doc/refman/5.6/en/string-functions.html#function_field
and in general (method is designed for strings but it will work just fine with numbers)
ORDER BY FIELD(field_name, value_1, value_2, ... )
However
It makes your SQL less portable
Ordering like this is much less efficient
Whole code
SELECT school_id, first_name, last_name, email, blog_username, comment_username
FROM table
WHERE user_id IN (100, 3, 72)
ORDER BY FIELD(user_id, 100, 3, 72)
Although I would consider changing the rest of you code so you do not have to use this method.