How to get the first rows after order - sql

How can I get only the first few rows,
After I performed order by to a table?
In SQL 2012, let's say I have a table:
----------------------
| Sales | ProductType |
----------------------
120 | Foodstuff
100 | Electronic
200 | Mobile
Now the problem is:
I select with order by Sales DESC
and I only want to get 2 rows.

You can use the limit clause.
SELECT *
FROM tablename
ORDER BY sales DESC
LIMIT n;
Where n is the number of rows you want to select

Related

Stop SQL Select After Sum Reached

My database is Db2 for IBM i.
I have read-only access, so my query must use only basic SQL select commands.
==============================================================
Goal:
I want to select every record in the table until the sum of the amount column exceeds the predetermined limit.
Example:
I want to match every item down the table until the sum of matched values in the "price" column >= $9.00.
The desired result:
Is this possible?
You may use sum analytic function to calculate running total of price and then filter by its value:
with a as (
select
t.*,
sum(price) over(order by salesid asc) as price_rsum
from t
)
select *
from a
where price_rsum <= 9
SALESID | PRICE | PRICE_RSUM
------: | ----: | ---------:
1001 | 5 | 5
1002 | 3 | 8
1003 | 1 | 9
db<>fiddle here

SQLite - Filter record based on specific calculated sum

I'm given a table with a varying number of records that contain persons, their weight, and an order value which determines in which order the persons should be chosen ...
create table line (
id int not null PRIMARY KEY,
name varchar(255) not null,
weight int not null,
turn int unique not null,
check (weight > 0)
);
I have to retrieve the last record from the table with which 1000 lbs is not exceeded when counting the person's weight together in order.
E.g. if the table is
id | name | weight | order |
---+---------------------+---------+-------+
5 | Mark | 250 | 1 |
4 | James | 175 | 5 |
3 | John | 350 | 2 |
6 | James | 400 | 3 |
1 | Rick | 500 | 6 |
2 | Mike | 200 | 4 |
The query should return only James, as the first three picked (per order) people's weight will fit within 1000 lbs. The sum of the weight of these three persons is 250 + 350 + 400 = 1000.
People with same name might be in the table. Therefore the id should be used for the calculation.
How would I write an SQLite statement that can filter this accordingly?
I should first order by order but from there on my SQL knowledge is too limited to figure out how to calculate the sum within 1000...
SELECT name, weight, order FROM line ORDER BY order ASC
We can do this with a correlated subquery:
SELECT
id,
name,
weight,
"order",
FROM line t1
WHERE
(SELECT SUM(t2.weight) FROM line t2 WHERE t2."order" <= t1."order") <= 1000
ORDER BY
"order" DESC
LIMIT 1;
The correlated subquery in the query above calculates the running sum of weight as given by the order. The WHERE clause just restricts to only line records whose cumulative weight does not exceed 1000. Then, we order descending by the order column with LIMIT 1 to target the James record.
By the way, avoid using SQL keywords like order to name your columns.
SQL syntax is not case-sensitive. Wrap column name inside []: [order]
SELECT name, weight, order FROM line ORDER BY [order] ASC

One one customer from table

I need help using Teradata SQL and I hope you can help.
I have a table that looks like this:
email | article number | discount | price
customer01#test.de | 123 | 15 | 999
customer01#test.de | 456 | 30 | 1999
customer01#test.de | 789 | 30 | 999
From this table I want only row from the customer which has the highest discount and (if there are multiple rows with the same discount) the lowest price.
So in the example above, I only want the 3rd line. How can I write a SQL query for this?
The most flexible way utilizes ROW_NUMBER:
select * from myTable
QUALIFY
ROW_NUMBER()
OVER (PARTITION BY email -- for each customer, otherwise remove it
ORDER BY discount DESC, price ASC) = 1
The simplest way to do this is via a simple select statement ordered by discount (descending) and then by price (ascending).
SELECT * FROM customers
ORDER BY discount DESC, price ASC
LIMIT 1
Use NOT EXISTS to return a row only if there are no other row with a higher discount, or another row with same discount and a lower price.
select *
from tablename t1
where not exists (select 1 from tablename t2
where t2.discount > t1.discount
or (t2.discount = t1.discount and t2.price < t1.price))

Sort by data from multiple columns

For customer reviews on my products, I have them stored in SQL something like the below:
durability | cost | appearance
----------------------------------
5 | 3 | 4
2 | 4 | 2
1 | 5 | 5
Each value is an out of five score in the three categories.
When I want to print this information on page, I'd like to order them in descending order by the average score of an individual review.
SELECT *
FROM reviews
ORDER BY (durability+cost+appearance)/3 DESC
Obviously this doesn't work, but is there a way to get my result? I don't want to include an average column in SQL because outside of this one small application, it serves zero purpose.
Use ORDER BY instead of SORT BY:
SELECT *
FROM reviews
ORDER BY (durability+cost+appearance)/3 DESC
EDIT:
To see the order by value, try adding one more column in the select clause:
SELECT *,(durability+cost+appearance)/3 as OrderValue
FROM reviews
ORDER BY (durability+cost+appearance)/3 DESC
Sample output:
DURABILITY COST APPEARANCE ORDERVALUE
5 3 4 4
1 5 5 3
2 4 2 2

PostgreSQL - repeating rows from LIMIT OFFSET

I noticed some repeating rows in a paginated recordset.
When I run this query:
SELECT "students".*
FROM "students"
ORDER BY "students"."status" asc
LIMIT 3 OFFSET 0
I get:
| id | name | status |
| 1 | foo | active |
| 12 | alice | active |
| 4 | bob | active |
Next query:
SELECT "students".*
FROM "students"
ORDER BY "students"."status" asc
LIMIT 3 OFFSET 3
I get:
| id | name | status |
| 1 | foo | active |
| 6 | cindy | active |
| 2 | dylan | active |
Why does "foo" appear in both queries?
Why does "foo" appear in both queries?
Because all rows that are returned have the same value for the status column. In that case the database is free to return the rows in any order it wants.
If you want a reproducable ordering you need to add a second column to your order by statement to make it consistent. E.g. the ID column:
SELECT students.*
FROM students
ORDER BY students.status asc,
students.id asc
If two rows have the same value for the status column, they will be sorted by the id.
For more details from PostgreSQL documentation (http://www.postgresql.org/docs/8.3/static/queries-limit.html) :
When using LIMIT, it is important to use an ORDER BY clause that constrains the result rows into a unique order. Otherwise you will get an unpredictable subset of the query's rows. You might be asking for the tenth through twentieth rows, but tenth through twentieth in what ordering? The ordering is unknown, unless you specified ORDER BY.
The query optimizer takes LIMIT into account when generating a query plan, so you are very likely to get different plans (yielding different row orders) depending on what you give for LIMIT and OFFSET. Thus, using different LIMIT/OFFSET values to select different subsets of a query result will give inconsistent results unless you enforce a predictable result ordering with ORDER BY. This is not a bug; it is an inherent consequence of the fact that SQL does not promise to deliver the results of a query in any particular order unless ORDER BY is used to constrain the order.
select * from(
Select "students".*
from "students"
order by "students"."status" asc
limit 6
) as temp limit 3 offset 0;
select * from(
Select "students".*
from "students"
order by "students"."status" asc
limit 6
) as temp limit 3 offset 3;
where 6 is the total number of records that is under examination.