SQL filtering for table based on 3rd column's value - sql

How should my SQL be so that the table mentioned above should have the expected output using SQL. The filtering happens using the col 3 value. Row with the highest col 3 value for a particular col 1 value is selected in the output.

You can use ROW_NUMBER() window function
SELECT col1, col2, col3 from (
SELECT row_number() over (partition by col1 order by col3 desc) sn, * from your_table_name
) a WHERE sn=1;

I assume you require the usage of the WHERE clause in SQL which acts as a method to filter results based on a conditional.
Considering you want all entries rather than any given entry one that matches, you can use the following (written in MySQL) which uses a nested SELECT statement:
SELECT *
FROM Table
WHERE col3=(SELECT MAX(col3) FROM Table);

Related

SQL Server Query - How to append row showing total record count?

What is the best approach to append a row to a SQL Server query showing the total count of rows resulting from the query? UNION is one way, but seems very inefficient:
SELECT col1, col2 FROM tbl1
UNION ALL
SELECT STR(COUNT(col1)), NULL FROM tbl1
ROLLUP isn't an option because it requires GROUP BY, which we're not using for the queries in question.
You can use GROUPING SETS for this
SELECT
CASE WHEN GROUPING(col1) = 0 THEN col1 ELSE CAST(COUNT(*) AS varchar(30)) END AS col1,
col2
FROM tbl1
GROUP BY GROUPING SETS (
(col1, col2),
()
);
The GROUPING function will tell you whether the row is the Total row or not.
This does have the effect of grouping the columns which could be a different result and possibly less efficient. But if you include a unique/primary key as the first column in the grouping list then this shouldn't make a difference, and should be almost as performant as the original query.
You can also use a window function, which will return the total on each row as another column
SELECT
col1,
col2,
COUNT(*) OVER ()
FROM tbl1;

how to select min value from table if table has two unique values with rest of columns are identical

ex:Input
ID Col1 Col2 Col3
-- ---- ---- ----
1 a a sql
2 a a hive
Out put
ID Col1 Col2 Col3
-- ---- ---- ----
1 a a sql
Here my id value and Col3 values are unique but i need to filter on min id and populate all records.
I know below approach will work, but any best approach other than this please suggest
select Col1,Col2,min(ID) from table group by Col1,Col2;
and join this on ID,Col1,Col2
I think you want row_number():
select t.*
from (select t.*, row_number() over (partition by col1, col2 order by id) as seqnum
from t
) t
where seqnum = 1
It appears that Hive supports ROW_NUMBER. Though I’ve never used hive, other rdbms would use it like this to get the entire contents of the min row without needing to join (doesn’t suffer problems if there are repeated minimum values)
SELECT a.* FROM
(
SELECT *, ROW_NUMBER() OVER(ORDER BY id) rn FROM yourtable
) a
WHERE a.rn = 1
The inner query selects all the table data and establishes an incrementing counter in order of ID. It could be based on any column, the min ID (in this case) being row number 1. If you wanted the max, order by ID desc
If you want the number to restart for different values of another column (eg of ten of your Col3 were “sql” and twenty rows had “hive”) you an say PARTITION BY col3 ORDER BY id, and the row number will be a counter that increments for identical values of col3, restarting from 1 for each distinct value of col3

How to use group-by and get other rows results

Question: if this is my data:
col1,col2,col3,col4
===================
www.com,0,dangerous,reason A
www.com,1,dangerous 2,reason B
I want the a single result where column 2 value is max, so I will use in my select the Max(col2) function - but how can I get those corresponding col3 and col4 row ?
select
col1, max(col2), col3, col4
group by
col1
and ???
Thanks
Idan
You can use order by and limit to one row. The ANSI-standard syntax is:
select t.*
from t
order by t.col2 desc
fetch first 1 row only;
Not all databases support the fetch first clause, so you might have to use select top 1, limit, or some other construct.
You can use where in select statement
Like
Select * from table name where col2=max(col2)
You can get max column entire row with single value
If the column col2 which contain same value like 1,1,2,2 at this time above query return the 2 rows. At that time if you want single row you want to use this
Select * from table name where col2=max(col2) fetch first 1 row only
Might be this helpful

Oracle: extract data from MDSYS.SDO_GEOMETRY column

I have a table form which I need to extract some information. This table has an oracle spatial (MDSYS.SDO_GEOMETRY) column, from which I also need some data.
I started out with a simple query like this:
select id, field1, field2
FROM my_table;
After that, I was able to loop over the result to extract the data that was in the spatial column:
SELECT *
FROM TABLE (SELECT a.POSITIONMAP.sdo_ordinates
FROM my_table
WHERE ID = 18742084);
The POSITIONMAP.sdo_ordinates seems to usually hold 4 values, like these:
100050,887
407294,948
0,577464740471056
-0,816415625470689
I need the last 2 values. I can achieve that by changing the query into this:
SELECT * FROM
(SELECT rownum AS num,
column_value AS orientatie
FROM TABLE (SELECT a.POSITIONMAP.sdo_ordinates
FROM my_table
WHERE ID = 18742084))
WHERE num IN (3,4)
Looping over every row from my first query to extract the data from the POSITIONMAP column is of course not very performance friendly, so my query becomes slow very quickly.
I would like to retrieve all information in one query, but there are a few things that prevent me from doing so.
Not every row in the table has data in POSITIONMAP
Some rows do have data in POSITIONMAP, but they only contain 2 values (so not the 3rd and 4th value that I am looking for.
I need the data in one row for every row in the table (using the previous query would result in duplicate rows
The closest I got is:
select
id,
field1,
field2
t.*
FROM my_table v,
table (v.POSITIONMAP.sdo_ordinates) t
This gives my 4 rows for every row in my_table.
As soon as I try to put the rownum condition into this query, I get an error: "invalid user.table.column, table.column, or column specification"
Is there any way to combine what I want to do into 1 query?
You can use sdo_util.getvertices as follows:
select t.x,t.y
from my_table mt
,table(sdo_util.getvertices(mt.positionmap)) t
where t.id = 2
I'm assuming that your geometries are lines (gtype=2002) and points (gtype= 2001). If you want X,Y values for lines and empty values for point you can filter on the sdo_gtype property of the geometry object.
select t.x,t.y
from my_table mt
,table(sdo_util.getvertices(mt.positionmap)) t
where t.id = 2
and mt.positionmap.sdo_gtype=2002
union all
select null as X,
null as Y
from my_table mt
where mt.positionmap.sdo_gtype=2001
One method is to use the ROW_NUMBER() analytic function:
SELECT *
FROM (
select id,
field1,
field2,
t.*,
ROW_NUMBER() OVER ( PARTITION BY v.id ORDER BY ROWNUM ) AS rn
FROM my_table v,
TABLE( v.POSITIONMAP.sdo_ordinates ) t
)
WHERE rn IN ( 3, 4 )

Numbering series of data in SQL

i have a little problem with SQL SELECT. I want to number continous groups of the same value in column nr 2:
1,'a'
2,'a,
3,'b'
4,'c'
5,'a'
6,'a'
7,'e'
8,'e'
The output i want :
1,'a',1
2,'a,,1
3,'b',2
4,'c',3
5,'a',4
6,'a',4
7,'e',5
8,'e',5
Is it possible to do it with just a select? I must do it in Vertica's SQL, its not supporting operations on variables in select, so i cant just declare a variable before and increment it somehow.
You could use CONDITIONAL_CHANGE_EVENT() which is pretty simple. Basically you send in the column that you want to trigger the sequence increment as a parameter, and you order it the way you need it in the window. It's a Vertica analytic function.
SELECT col1,
col2,
CONDITIONAL_CHANGE_EVENT(col2) OVER ( ORDER BY col1 )
FROM mytable
You can do this with window functions. One method uses lag() and then does a cumulative sum of when the value changes:
select t.col1, t.col2,
sum(case when col2 = prev_col2 then 0 else 1 end) over (order by col1) as newcol
from (select t.*,
lag(col2) over (order by col1) as prev_col2
from t
) t