How can I get the X data in a SELECT QUERY - sql-server-2008

For example: If I have a table where contains:
PRICES
1
5
3
8
2
8
If I'd like the the second element, how can I get it? Only that number.. Is it possible?

Try this:
declare #x int
set #x = 3
select top 1
from (select top #x from table order by 1 desc) xx

$third_element = mysql_result(mysql_query("SELECT prices FROM the_table WHERE prices = '3'"), 0);
That selects the element, but I don't know why you would want to do it like that unless you had another row to select it from like, WHERE other_row = 'something', then you would arrive at 3.

yes it is possible
here is the solution for your answer try this.
create table prices
(
price int
)
insert into prices values (1)
insert into prices values (5)
insert into prices values (3)
insert into prices values (8)
insert into prices values (2)
insert into prices values (8)
select x.* from
(
select ROW_NUMBER()over(order by price) as RowNumber,price
from prices
)x
where x.RowNumber=3

Related

Extract only rows with highest values

I am relatively new to SQL and I am trying to extract rows where they have the highest values.
For example, the table look like this:
user_id fruits
1 apple
1 orange
2 apple
1 pear
I would like to extract the data such that it would look like this:
user_id fruits
1 3
If user_id 2 has 3 fruits, it should display:
user_id fruits
1 3
2 3
I can only manage to get the if I use LIMIT = 1 by DESC order, but that is not the right way to do it. Otherwise I am getting only:
user_id fruits
1 3
2 1
Not sure where to store the max value to put in the where clause. Appreciate any help, thank you
Use RANK():
WITH cte AS (
SELECT user_id, COUNT(*) AS cnt, RANK() OVER (ORDER BY COUNT(*) DESC) rnk
FROM yourTable
GROUP BY user_id
)
SELECT user_id, cnt AS fruits
FROM cte
WHERE rnk = 1;
Here's one answer (with sample data):
CREATE TABLE something (user_id INT NOT NULL, fruits VARCHAR(10) NOT NULL, PRIMARY KEY (user_id, fruits));
INSERT INTO something VALUES (1, 'apple');
INSERT INTO something VALUES (1, 'orange');
INSERT INTO something VALUES (2, 'apple');
INSERT INTO something VALUES (1, 'pear');
INSERT INTO something VALUES (2, 'orange');
INSERT INTO something VALUES (2, 'pear');
SELECT user_id, COUNT(*) AS cnt
FROM something
GROUP BY user_id
HAVING COUNT(*) >= ALL (SELECT COUNT(*) FROM something GROUP BY user_id);

MySQL ORDER BY two clauses (descending and ascending)

I have this table:
create table products(name text, quantity int);
insert into products values ("A", 10);
insert into products values ("B", 0);
insert into products values ("C", 15);
insert into products values ("D", 0);
insert into products values ("E", 17);
I would like to order by product name, but keep products with quantity = 0 at the bottom, like this:
name quantity
A 10
C 15
E 17
B 0
D 0
I've tried:
select * from products order by quantity desc, name asc; but it but while it correctly keeps quantity = 0 at the bottom, name ordering is reversed. Is ORDER BY even the right thing to use in this case?
SQL Fiddle: http://sqlfiddle.com/#!9/6985a4/1/0
I would use:
order by (quantity = 0), name
Boolean values are ordered with "false" first then "true".
I would use this to be explicit, rather than using a special value such as 'z' -- which won't even work if you have names that start with 'z'.
Try this:
select * from products
order by case when quantity = 0 then "z" else name end asc;
You can try it like this:
SELECT * FROM (
select name, quantity from products WHERE quantity>0 order by name) t1
UNION
select name, quantity from products t2 WHERE quantity<=0;

Comparing n with (n-1) and (n-2) records in SQL

Write a SQL statement which can generate the list of customers whose minutes Streamed is consistently less than the previous minutes Streamed. As in minutes Streamed in the nth order is less than minutes Streamed in n-1th order, and the next previous order is also less. Another way to say it, list the customers that watch less and less minutes each time they watch a movie.
The table, query:
sqlfiddle link:
I have come up with the following query:
select distinct c1.customer_Id
from Customer c1
join Customer c2
where c1.customer_Id = c2.customer_Id
and c1.purchaseDate > c2.purchaseDate
and c1.minutesStreamed < c2.minutesStreamed;
This query doesn't deal with the (n-1)st and (n-2)nd comparison, i.e. "minutes Streamed in the nth order is less than minutes Streamed in n-1th order, and the next previous order is also less." condition.
I have attached a link for sqlfiddle, where I have created the table.
Hello Continuous Learner,
the following statement works for the n-1 and n-2 relation.
select distinct c1.customer_Id
from Customer c1
join Customer c2
on c1.customer_Id = c2.customer_Id
join Customer c3
on c1.customer_Id = c3.customer_Id
where c1.purchaseDate < c2.purchaseDate
and c1.minutesStreamed > c2.minutesStreamed
and c2.purchaseDate < c3.purchaseDate
and c2.minutesStreamed > c3.minutesStreamed
Although, I currently don't have an automatic solution for this problem.
Cheers
I would use a ROW_NUMBER() function with partition by customer id.
and then do a self join, on customer id and rank = rank-1, to bring new and old at the same level
Like:
create temp_rank_table as
(
select
customer_Id,
purchaseDate ,
minutesStreamed,
ROW_NUMBER() OVER (PARTITION BY customer_Id, ORDER BY purchaseDate, minutesStreamed) as cust_row
from Customer
)
self join
select customer_Id
( select
newval.customer_Id,
sum(case when newval.minutesStreamed < oldval.minutesStreamed then 1 else 0 end) as LessThanPrevCount,
max(newval.cust_row) as totalStreamCount
from temp_rank_table newval
left join temp_rank_table oldval
on newval.customer_id = oldval.customer_id
and newval.cust_row-1 = oldval.cust_row -- cust_row 2 matches to cust_row 1
group by newval.customer_id
)A
where A.LessThanPrevCount = (A.totalStreamCount-1)
-- get customers who always stream lesser than previous
--you can use having clause instead of a subquery too
DECLARE #TBL AS TABLE ( [NO] INT, [CODE] VARCHAR(50), [AREA]
VARCHAR(50) )
/* EXAMPLE 1 */ INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES
(1,'001','A00') INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES
(2,'001','A00') INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES
(3,'001','B00') INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES
(4,'001','C00') INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES
(5,'001','C00') INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES
(6,'001','A00') INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES
(7,'001','A00')
/* EXAMPLE 2 / / ***** USE THIS CODE TO ENTER DATA FROM DIRECT TABLE
***** SELECT ROW_NUMBER() OVER(ORDER BY [FIELD_DATE]) AS [NO] ,[FIELD_CODE] AS [CODE] ,[FIELD_AREA] AS [AREA] FROM TABLE_A WHERE
CAST([FIELD_DATE] AS DATE) >= CAST('20200307' AS DATE) ORDER BY
[FIELD_DATE],[FIELD_CODE]
*/
SELECT A.NO AS ANO ,A.CODE AS ACODE ,A.AREA AS AAREA ,B.NO AS BNO
,B.CODE AS BCODE ,B.AREA AS BAREA ,CASE WHEN A.AREA=B.AREA THEN
'EQUAL' ELSE 'NOT EQUAL' END AS [COMPARE AREA] FROM #TBL A LEFT JOIN
#TBL B ON A.NO=B.NO+1
Blockquote

Calculate proper total in query?

I have a table like this
| customer_id | item_id | price | amount |
I want to retrieve the amount of money each customer has spent in a single query.
I have tried:
SELECT SUM(price * amount) AS total FROM table GROUP BY customer_id
but this spits out astronomically high values for total. It cannot be correct.
I also tried
SELECT #total := #total + (price * amount) AS total FROM table
CROSS JOIN (SELECT #total := 0) CONST
GROUP BY customer_id
but this doesn't start from 0 for each customer, so the previous totals will stack up...
How do I properly retrieve the data I want?
Your initial query is correct:
SELECT SUM(price * amount) AS total
FROM table
GROUP BY customer_id;
(although I would include customer_id in the SELECT clause.)
If you have "astronomically high values" then the issue is your data. Quite possibly, the issue is that "price" is really "total" on each row.
You have to add customer id to your select clause.
I think your query should be correct. I tried on my server the following:
create table test (customer_id int, item_id int, price money, amount int)
insert test values (1,1,10,2)
insert test values (1,2,12,4)
insert test values (2,1,10,2)
insert test values (2,3,5,1)
insert test values (2,4,0.5,21)
SELECT customer_id,sum(price*amount) FROM test
GROUP BY customer_id
I think you need something like this:
select customer_id,sum(price * amount) from table group by customer_id

SQL. How to work/compare/find differences within different rows in the same table

I have a table which looks like this:
ID Date Size Marked
1 2010-02-02 2 X
2 2002-02-02 1
1 2010-02-03 2 X
2 2010-02-03 3
3 2010-02-03 4 X
And I have a code (PHP) which does following things:
a) Calculate sum of sizes per day
b) Find the difference between total for this day and last day.
c) Find the sum of sizes for rows which became marked this day (the row with the same id wasn't marked yesterday).
As example, I will get following results:
Date Total DiffWithYesterday MarkedThisDay
2010-02-02 3 0 0
2010-02-03 9 6 4
I have feeling that there is a way to write this in SQL. However I am quite weak in SQL, so I gave up after a day playing around inner joins, group by and embedded selects.
I would appreciate, if you give me some clues how to do that.
Oh.. And I am using MySQL.
Regards,
Victor
had fun with this one.
SELECT
today.date as Date,
today.total as Total,
(today.total - yesterday.total) as DiffWithYesterday ,
marked.total as MarkedThisDay
FROM
(SELECT date, sum(size) as total
FROM table_name
GROUP BY date) today
LEFT JOIN
(SELECT date, sum(size) as total
FROM table_name
WHERE marked = 'X'
GROUP BY date) marked ON today.date = marked.date
LEFT JOIN
(SELECT (date + INTERVAL 1 day) as date, sum(size) as total
FROM table_name
GROUP BY date) yesterday ON today.date=yesterday.date
obviously, you will need to replace "table_name" with the name of your table
Something like this works in SQL Server. I don't have MySQL to test but you can probably convert once you see the logic.
create table so (sodate datetime, sosize int, somarked varchar(1))
insert into so (sodate,sosize,somarked) values ('1-jan-2010',3,'X')
insert into so (sodate,sosize,somarked) values ('2-jan-2010',1,'X')
insert into so (sodate,sosize,somarked) values ('3-jan-2010',2,'X')
insert into so (sodate,sosize,somarked) values ('4-jan-2010',0,null)
insert into so (sodate,sosize,somarked) values ('5-jan-2010',2,null)
insert into so (sodate,sosize,somarked) values ('6-jan-2010',1,null)
insert into so (sodate,sosize,somarked) values ('6-jan-2010',4,null)
insert into so (sodate,sosize,somarked) values ('6-jan-2010',1,null)
insert into so (sodate,sosize,somarked) values ('7-jan-2010',3,'X')
insert into so (sodate,sosize,somarked) values ('8-jan-2010',3,'X')
insert into so (sodate,sosize,somarked) values ('9-jan-2010',2,null)
insert into so (sodate,sosize,somarked) values ('10-jan-2010',2,'X')
insert into so (sodate,sosize,somarked) values ('11-jan-2010',1,'X')
insert into so (sodate,sosize,somarked) values ('12-jan-2010',2,null)
insert into so (sodate,sosize,somarked) values ('13-jan-2010',3,'X')
select so.sodate
,sum(so.sosize) as Total
,isnull(sum(so.sosize),0) - isnull(min(so2.sosize),0) as DiffFromYesterday
,sum(case when so.somarked = 'X' then so.sosize end) as MarkedThisDay
from so
left join (select so.sodate,sum(so.sosize) sosize from so group by sodate) so2 on dateadd(dd,1,so2.sodate) = so.sodate
group by so.sodate
..and after installing mysql this seems to work there...
select so.sodate
,sum(so.sosize) as Total
,ifnull(sum(so.sosize),0) - ifnull(min(so2.sosize),0) as DiffFromYesterday
,sum(case when so.somarked = 'X' then so.sosize end) as MarkedThisDay
from so
left join (select so.sodate,sum(so.sosize) sosize from so group by sodate) so2 on (so2.sodate + INTERVAL 1 day )= so.sodate
group by so.sodate ;