SQL Order by descending total last - sql

I would like to set my order by to descending but with my total row(sums up all numerical values in a specific column) as last row as last in sequence, is this possible?
DB is netezza, and there are only three columns: ID, name and revenue which is an aggregated column to begin with

This fiddle was created in MySQL, but the query should work in any standard SQL.
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE t1 ( id int, name varchar(10), revenue int ) ;
INSERT INTO t1 (id, name, revenue)
VALUES (1,'first',10), (2,'first',10), (3,'last',1), (4,'last',1) ;
Main Query:
SELECT name, sum(revenue) AS totalRevenue
FROM t1
GROUP BY name
ORDER BY totalRevenue DESC
Results:
| name | totalRevenue |
|-------|--------------|
| first | 20 |
| last | 2 |

You can accomplish this with a UNION ALL.
SELECT column_A , column_B , ... {your query}
UNION ALL
SELECT '' as Column_A , SUM(column_B) as column_B,... {your totals query}
column_B in this case can be whichever numerical column that you want totals for. column_A is a non-numerical column or any column you do not want a total for. Note that all columns selected in {your totals query} should be aggregated or NULL if you want this to return only a single row.
You will also need to include the same number of columns in both queries for the UNION method to work properly.
If you include your RMDB, then we can tailor a more specific solution. UNION ALL is the syntax for SQL-Server.
-- so in response to your comment 9/6, it sounds like you can run an offset fetch command.
SELECT {your query} OFFSET 1
UNION ALL
SELECT {your query} OFFSET 0 FETCH NEXT 1 ROW ONLY
Keep the ORDER BY the same for both queries or you will get unexpected results.

One approach is to use grouping sets:
select id, name, sum(revenue)
from t
group by grouping sets ( (id, name), () )
order by (case when grouping(id) = 1 then 1 else 2 end) desc,
sum(revenue) desc;

Related

Find unique row when two rows when two row have the column id as the same, but have other column a date which I want the newset one

Create a query of unique values, but some of them have same ids but different dates. Just want the newest date. I am joining several tables, but do not know how to handle this
SELECT DISTINCT ap.id, MAX(ap.date)
FROM sometable;
I tried this code but no result.
I get these resulst:
id date
------------
1 10/31/18
1 10/15/18
2 11/05/17
2 11/04/17
But I want these results:
1 10/31/18
2 11/05/17
In case your query has other columns too that you want to show in result, you will have to resort to analytical function, in such case your query will look like following
select id, the_date /* ,other columns */ from (
select row_number() over (partition by id
order by some_date /* your date column */ desc ) ord,
id,
some_date the_date
/* ,other columns */
from <your_table>
) where ord = 1
;
You need group by
SELECT ap.id, MAX(ap.date)
from sometable ap
group by ap.id;
the aggregation function as min(), max() ,, count() need group by for return the related agreagated result
and for the query in you comment you should use
SELECT ap.id, MAX(ap.date)
from sometable ap
where ap.id in ( id1, id2, id3.... idns)
group by ap.id

Get any not null value of other fileds in aggregations

I want to aggregate on some fields and get any not null value on others. To be more precise the query looks something like:
SELECT id, any_value(field1), any_value(field2) FROM mytable GROUP BY ID
and the columns are like:
ID | field1 | field 2
-----------------
id | null | 3
id | 1 | null
id | null | null
id | 2 | 4
and the output can be like (id, 1,4) or (id,2,4) or ... but not something like (id, 1, null)
I can't find in the docs if any_value() is guaranteed to return a not null row if there is one (although it did so in my experiments) or may return a row with null value even if there are some not null values.
Does any_value() perform the task I described? If not what way to you suggest for doing it?
This is sort of a guess, but have you tried:
SELECT id, MIN(field1), MAX(field2)
FROM mytable
GROUP BY id;
This will ignore NULL values return different values from the two columns.
You can use analyatical functions as well.
Below is the query (SQL server):
select id, field1, field2
from (select id, field1, field2, row_number()
over (partition by id order by isnull(field1, 'ZZZ') asc, isnull(field2, 'ZZZ') asc) as RNK from mytable) aa
where aa.RNK = 1;
This will return only one row, you can change the order in order by clause if you are looking for maximun value in any column.
This could be achieved by aggregating to array with 'ignore nulls' specified and taking the first element of the resulting array. Unlike MIN/MAX solution, you can use it with structs
SELECT
id,
ARRAY_AGG(field1 IGNORE NULLS LIMIT 1)[SAFE_OFFSET(0)],
FROM
mytable
GROUP BY
id

SQL. Is there any efficient way to find second lowest value?

I have the following table:
ItemID Price
1 10
2 20
3 12
4 10
5 11
I need to find the second lowest price. So far, I have a query that works, but i am not sure it is the most efficient query:
select min(price)
from table
where itemid not in
(select itemid
from table
where price=
(select min(price)
from table));
What if I have to find third OR fourth minimum price? I am not even mentioning other attributes and conditions... Is there any more efficient way to do this?
PS: note that minimum is not a unique value. For example, items 1 and 4 are both minimums. Simple ordering won't do.
SELECT MIN( price )
FROM table
WHERE price > ( SELECT MIN( price )
FROM table )
select price from table where price in (
select
distinct price
from
(select t.price,rownumber() over () as rownum from table t) as x
where x.rownum = 2 --or 3, 4, 5, etc
)
Not sure if this would be the fastest, but it would make it easier to select the second, third, etc... Just change the TOP value.
UPDATED
SELECT MIN(price)
FROM table
WHERE price NOT IN (SELECT DISTINCT TOP 1 price FROM table ORDER BY price)
To find out second minimum salary of an employee, you can use following:
select min(salary)
from table
where salary > (select min(salary) from table);
This is a good answer:
SELECT MIN( price )
FROM table
WHERE price > ( SELECT MIN( price )
FROM table )
Make sure when you do this that there is only 1 row in the subquery! (the part in brackets at the end).
For example if you want to use GROUP BY you will have to define even further using:
SELECT MIN( price )
FROM table te1
WHERE price > ( SELECT MIN( price )
FROM table te2 WHERE te1.brand = te2.brand)
GROUP BY brand
Because GROUP BY will give you multiple rows, otherwise you will get the error:
SQL Error [21000]: ERROR: more than one row returned by a subquery used as an expression
I guess a simplest way to do is using offset-fetch filter from standard sql, distinct is not necessary if you don't have repeat values in your column.
select distinct(price) from table
order by price
offset 1 row fetch first 1 row only;
no need to write complex subqueries....
In amazon redshift use limit-fetch instead for ex...
Select distinct(price) from table
order by price
limit 1
offset 1;
You can either use one of the following:-
select min(your_field) from your_table where your_field NOT IN (select distinct TOP 1 your_field from your_table ORDER BY your_field DESC)
OR
select top 1 ColumnName from TableName where ColumnName not in (select top 1 ColumnName from TableName order by ColumnName asc)
I think you can find the second minimum using LIMIT and ORDER BY
select max(price) as minimum from (select distinct(price) from tableName order by price asc limit 2 ) --or 3, 4, 5, etc
if you want to find third or fourth minimum and so on... you can find out by changing minimum number in limit. you can find using this statement.
You can use RANK functions,
it may seem complex query but similar results like other answers can be achieved with the same,
WITH Temp_table AS (SELECT ITEM_ID,PRICE,RANK() OVER (ORDER BY PRICE) AS
Rnk
FROM YOUR_TABLE_NAME)
SELECT ITEM_ID FROM Temp_table
WHERE Rnk=2;
Maybe u can check the min value first and then place a not or greater than the operator. This will eliminate the usage of a subquery but will require a two-step process
select min(price)
from table
where min(price) <> -- "the min price you previously got"

Row with the highest ID

You have three fields ID, Date and Total. Your table contains multiple rows for the same day which is valid data however for reporting purpose you need to show only one row per day. The row with the highest ID per day should be returned the rest should be hidden from users (not returned).
To better picture the question below is sample data and sample output:
ID, Date, Total
1, 2011-12-22, 50
2, 2011-12-22, 150
The correct result is:
2, 2012-12-22, 150
The correct output is single row for 2011-12-22 date and this row was chosen because it has the highest ID (2>1)
Assuming that you have a database that supports window functions, and that the date column is indeed just date (and not datetime), then something like:
SELECT
* --TODO - Pick columns
FROM
(
SELECT ID,[Date],Total,ROW_NUMBER() OVER (PARTITION BY [Date] ORDER BY ID desc) rn
FROM [Table]
) t
WHERE
rn = 1
Should produce one row per day - and the selected row for any given day is that with the highest ID value.
SELECT *
FROM table
WHERE ID IN ( SELECT MAX(ID)
FROM table
GROUP BY Date )
This will work.
SELECT *
FROM tableName a
INNER JOIN
(
SELECT `DATE`, MAX(ID) maxID
FROM tableName
GROUP BY `DATE`
) b ON a.id = b.MaxID AND
a.`date` = b.`date`
SQLFiddle Demo
Probably
SELECT * FROM your_table ORDER BY ID DESC LIMIT 1
Select MAX(ID),Data,Total from foo
for MySQL
Another simple way is
SELECT TOP 1 * FROM YourTable ORDER BY ID DESC
And, I think this is the most simple way!
SELECT * FROM TABLE_SUM S WHERE S.ID =
(
SELECT MAX(ID) FROM TABLE_SUM
WHERE CDATE = GG.CDATE
GROUP BY CDATE
)

SQL Query to get all rows with duplicate values but are not part of the same group

The database schema is organized as follows:
ID | GroupID | VALUE
--------------------
1 | 1 | A
2 | 1 | A
3 | 2 | B
4 | 3 | B
In this example, I want to GET all Rows with duplicate VALUE, but are not part of the same group. So the desired result set should be IDs (3, 4), because they are not in the same group (2, 3) but still have the same VALUE (B).
I'm having trouble writing a SQL Query and would appreciate any guidance. Thanks.
So far, I'm using SQL Count, but can't figure out what to do with the GroupId.
SELECT *
FROM TABLE T
HAVING COUNT(T.VALUE) > 1
GROUP BY ID, GroupId, VALUE
The simplest method for this is using EXISTS:
SELECT
ID
FROM
MyTable T1
WHERE
EXISTS (SELECT 1
FROM MyTable
WHERE Value = t1.Value
AND GroupID <> t1.GroupID)
Here is one method. First you have to identify the values that appear in more than one group and then use that information to find the right rows in the original table:
select *
from t
where value in (SELECT value
FROM TABLE T
GROUP BY VALUE
HAVING COUNT(distinct groupid) > 1
)
order by value
Actually, I prefer a slight variant in this case, by changing the HAVING clause:
HAVING min(groupid) <> max(groupid)
This works when you are looking for more than one group and should be faster than the COUNT DISTINCT version.
SELECT ALL_.*
FROM (SELECT *
FROM TABLE_
GROUP BY ID, GROUPID, VALUE
ORDER BY ID) GROUPED,
TABLE_ ALL_
WHERE GROUPED.VALUE = ALL_.VALUE
AND GROUPED.GROUPID <> ALL_.GROUPID