More than one result on request with limit 1 sqllite - sqlite

The result is one line, but there are several people with the same value of the bonus field
SELECT Name, bonus
From employees
ORDER by bonus
Limit 1
result
Ivan 100
but it is required that it was
Ivan 100
Petr 100
did this, but it seems very confusing to me:
SELECT Name, bonus
From employees
Where bonus= (SELECT id From employees ORDER by bonus Limit 1)

In SQLite you can achieve that by using RANK or dense_rank window function
select name, bonus
from (select name, bonus, dense_rank() over(order by bonus desc) dns_rnk from employees)
where dns_rnk = 1;
In sub-query it will rank employees on bonus and the outer query will filter out unneeded lines.

Related

Would these two SQLite queries generate the same result?

I'm working through this exercise.
On question 4, the goal is to find employees hired after "Jones". I think this problem can be solved without a join like so:
SELECT first_name, last_name, hire_date
FROM employees
WHERE hire_date > (
SELECT hire_date FROM employees WHERE last_name = "Jones"
)
But the answer on the website suggests:
SELECT e.first_name, e.last_name, e.hire_date
FROM employees e
JOIN employees davies
ON (davies.last_name = "Jones")
WHERE davies.hire_date < e.hire_date;
Are these more-or-less the same or is there a reason the second answer should be considered better?
I assume that the column last_name is defined as UNIQUE, so that the subquery in the 1st query returns only 1 row.
If not, then the queries do not return the same results, because although the subquery in the 1st query may return more than 1 row (and in other databases the query would not even run), SQLite will pick just the 1st of the returned rows and use its hire_date to compare it with all the rows of the table, while the join will use all the rows where last_name = "Jones".
If my assumption is correct then the 2 queries are equivalent, but the 1st one is what I would suggest because it is more readable and I believe it would perform better than the join.
If I had to use a join for this requirement (since it is homework) I would choose a more readable form:
SELECT e.first_name, e.last_name, e.hire_date
FROM employees e
JOIN (SELECT * FROM employees WHERE last_name = "Jones") t
ON t.hire_date < e.hire_date;

Need to apply Primary Indexes and secondary indexes in teradata tables

Can some one please help in solving my problem
I have three tables to be joined ed using indexes in Teradata to improve performance. Query specified below:-
Select b.Id, b.First_name, b.Last_name, c. Id,
c.First_name, c.Last_name, c.Result
from
(
select a.Id, a.First_name, a. Last_name, a.Approver1, a.Approver2
From table1 a
Inner join table2 d
On a.Id =D.Id
and A.Approver1 =a.Approver1
And a.Approve2 =D.Approver2
) b
Left join
(
select * from table3
where result is not null
and application like 'application1'
) c
On c. Id=b.Id
Group by b.Id, b.First_name, b.Last_name, c.Id,
c.First_name, c.Last_name, c.Result
The above query is taking so much of time since PI not defined correctly.
First two tables (table1 and 2) are with same set of columns hence pi can be defined like PI on I'd, approve1, approve2
However, while joining with table3 am confused and need to understand how to define pi. Is it something that PI can only work when we have same set of columns in the tables?
Structure of table3 is
I'd, first name, last name, result
And table 1 and table2
Id , First name, Last name, Approved 1, Approved 2, Results
Can you please help in defining primary indexes so that query can be optimised.
Teradata will usually not use Secondary Indexes for joins. The best PI would be id for all three tables, of course you need to check if there are not too many rows per value and it's not too skewed.
GROUP BY can be simplified to a DISTINCT, why do you need it, can you show the Primary Keys of those tables?
Edit based on comment:
PI-based joins are by far the fastest way. But you should be able the get rid of the DISTINCT, too, it's always a huge overhead.
Try replacing the 1st join with a NOT EXISTS:
Select b.Id, b.First_name, b.Last_name, c. Id,
c.First_name, c.Last_name, c.Result
from
(
select a.Id, a.First_name, a. Last_name, a.Approver1, a.Approver2
From table1 a
WHERE EXISTS
(
SELECT *
FROM table2 d
WHERE a.Id =D.Id
and A.Approver1 =a.Approver1
And a.Approve2 =D.Approver2
)
) b
Left join
(
select * from table3
where result is not null
and application like 'application1'
) c
On c. Id=b.Id

COUNT and DISTINCT without group by

I've two tables. One with clients, other with products bought by clients.
When I want to get the list of all products and clients, I do:
SELECT client_name, prod_id FROM TAB_CLIENT
INNER JOIN TAB_PROD ON prod_client = client_name
So I get (eg)
Henri - Potatoes
Henri - Chocolate
Tom - Beer
Nice. Now I want to know how many different clients I have.
So I tried to use COUNT and DISTINCT. Like this:
SELECT COUNT(DISTINCT client_name) AS num_client, client_name, prod_id
FROM TAB_CLIENT
INNER JOIN TAB_PROD ON prod_client = client_name
I want to get:
2 - Henri - Potatoes
2 - Henri - Chocolate
2 - Tom - Beer
So "2" in first colum as the whole number of different clients is 2 (Henri and Tom), name of the client at second colum and name of product as third colume.
But in fact if I add the count(distinct), I get only ONE result (seems like if there was a "group by" on num_client). And I don't want to GROUP BY on client_name as in this case I'll loose the product.
Is it possible to perform that in one query, or do I have to perform one select for counting and an other to get the result?
I notice all examples given in Stack are about Count/Distinct returning only number but not the number AND results.
Thanks
PS: I'm running MariaDB.
SELECT
( SELECT COUNT(DISTINCT client_name) FROM TAB_CLIENT ) AS Number_of_clients,
client_name,
prod_id
FROM TAB_CLIENT
INNER JOIN TAB_PROD ON prod_client = client_name

find count of distinct values in a column

Hi all am trying to build a sql query to display some information on a dashboard.
I have a table in which i store my sales data.My query needs to find total sales in last 7 days,average and group it based on region(which is present in user table.) .I created a temp table to get the item sales.DashBoard_Items table contains particular item that needs to be shown on dashboard.Now my problem is i need to get the store count of each region to find average sales.Can some one please help
Declare #TableTest
table(itemid int,itemname varchar(100),itemdescription varchar(100),id int,itemidd int,userid int,orderdate varchar(40),qty int)
insert into #TableTest
select * from DashBoard_Items join
SalesQTY on SalesQTY.OrderDate>= CONVERT(varchar(10) , DATEADD(DAY,-7,GETDATE()),126)
and OOS_DashBoard_CoreItems.itemid=SalesQTY.itemid
select distinct t.userid,u.region from #TableTest t join users u on t.userid=u.userid and region is not null
above select query returns
how can i get region count from the above select query
region count
5 - SUN WEST 2
2 - LONG ISLAND 3
You need to group by region and then use cont(*)
SELECT region, count(*)
FROM #TableTest
GROUP BY region;
Please try:
SELECT
Region,
COUNT(*) AS [Count]
FROM YourTable
GROUP BY Region
OR
SELECT
DISTINCT Region,
COUNT(*) OVER (PARTITION BY Region) AS [Count]
FROM YourTable
SELECT u.region, COUNT(*)
FROM #TableTest t JOIN users u ON t.userid=u.userid AND u.region IS NOT NULL
GROUP BY u.region
try
SELECT region, count( * )
FROM mytable
GROUP BY region

Compare (< or >) the result of one column, against the result of another column of two select statements? - Oracle

Question:
How do you compare (< or >) the result of one column, against the result of another column of two select statements?
More details:
I need to get a list only of the sold out movies. To do this, I need to check if
the number on the rented_movie_count on the first select statement is equal or greater than the number on the available_movie_count on the second select statement.
First Statement
result of the
select MOVIE_ID, count(MOVIE_ID) as rented_movies_count
from MOVIE_QUEUE
WHERE STATUS_ID=2
group by MOVIE_ID;
Second Statement
select MOVIE_ID, count(MOVIE_ID) as available_movie_count
from dvd
group by MOVIE_ID;
I am still very new to this and I am trying to learn, even suggestions about what kind of
syntax (operators, expressions, etc) should I use will help at least point me on a a directions to do more research. Thanks in advance
Given your database structure, a possible solution would be
SELECT rented.MOVIE_ID
,rented_movies_count
,available_movie_count
FROM (
SELECT MOVIE_ID, count(MOVIE_ID) AS rented_movies_count
FROM MOVIE_QUEUE
WHERE STATUS_ID=2
GROUP BY MOVIE_ID
) rented
,(SELECT MOVIE_ID, count(MOVIE_ID) AS available_movie_count
FROM dvd
GROUP BY MOVIE_ID
) available
WHERE rented.movie_id = available.movie_id
AND rented_movies_count >= available_movie_count
;
I've set up an example on http://www.sqlfiddle.com/#!4/3fc59/11 to test. But I guess that's more or less what you've come up with.
But I somewhat doubt that your database structure is really optimal!? Do you really store more than one record for a singe movie_id in the table dvd?
Wouldn't it be more useful to have exactly one record per movie_id in dvd along with some movie attributes and store the rental status of the dvds in movie_queue.status_id?
If movie_queue.status_id is defined as say
...available
...rented
Then your query would be much more easy:
SELECT MOVIE_ID
,count(case when status_id = 1 then 1 end) AS available_movie_count
,count(case when status_id = 2 then 1 end) AS rented_movies_count
FROM MOVIE_QUEUE
GROUP BY MOVIE_ID
HAVING count(case when status_id = 2 then 1 end) >= count(case when status_id = 1 then 1 end)
;
See for example http://www.sqlfiddle.com/#!4/13739/1

Resources