Task: selecting specified record in top of results list
my ugly variant:
(select * from mytable where id = 42)
union all
(select * from mytable where id != 42 order by id)
besides of ansi query variant for mysql is also would be very interesting to me
There is no difference between ANSI and vendor SQL solutions
select *
from mytable
order by
CASE WHEN id = 42 THEN 0 ELSE 1 END, id
Note: there is no guaranteed or implied order to a table or SELECT without an ORDER BY clause
Assuming id is always positive, try:
select *
from mytable
order by CASE WHEN id = 42 THEN 0 ELSE id END
Related
In SQL, where we need to filter the unnecessary data from a table:
case 1: if 2 IDs are same and DOD is not null then Record is needed
case 2: if single id is there and dod is not null then Record is needed
case 3: if 2 ids are same and if DOD is null for any one of them ,then record is not needed
Your help is much appreciated.
Thanks
You can use analytic functions for this:
select t.*
from (
select
t.*,
sum(case when dod is null then 1 else 0 end) over(partition by id) no_nulls
from mytable t
) t
where no_nulls = 0
Note that this also excludes records that have no duplicate id but whose dod is null (you did not describe how to handle those).
You could also use not exists (which can conviniently be turned to a delete statement if needed):
select t.*
from mytable t
where not exists(select 1 from mytable t1 where t1.id = t.id and t1.dod is null)
where no_nulls = 0
I'm working with a dataset - structured like this
I want to exclude all records with ReviewRound being "a" if they have gone through review round "b" - If a set of unique ID's has an associated round "b" review, the round "a" review should not be included.
Some records have not gone to round "b". The issues I'm running into are as a result of there being multiple records for each unique ID.
Ideally this could be done in GoogleBigQuery, if not, filtering through GoogleScripts may also be an option!
Any suggestions would be appreciated!
If a set of unique ID's has an associated round "b" review, the round "a" review should not be included.
If I followed you correctly, you could express this as a not condition with a correlated subquery that ensures that, if the current record has ReviewRound = 'a', there is no other record that has the same id and ReviewRound = 'b'.
select t.*
from mytable t
where not (
t.ReviewRound = 'a'
and exists (
select 1
from mytable t1
and t1.id = t.id and t1.ReviewRound = 'b'
)
)
You can do this with window functions as well:
select t.* except (num_bs)
from (select t.*,
countif(reviewround = 'b') over (partition by id) as num_bs
from t
) t
where num_bs = 0 or reviewround = 'b';
By using window functions, you can solve it with this query
SELECT ID, Score
FROM (
SELECT *,
MAX(CASE WHEN ReviewRound = 'b' THEN 1 ELSE 0 END) OVER (partition by ID) as has_b
FROM mytable
) t
WHERE has_b = 0
Re-conceptualizing as keeping only the latest review round, I would try:
select * from mytable join
(select ID, max(ReviewRound) as ReviewRound from mytable group by ID)
on (ID, ReviewRound)
I'm thinking about a SQL query that returns me all entries from a column whose first 5 characters match. Any ideas?
I'm thinking about entries where ANY first 5 characters match, not specific ones. E.g.
HelloA
HelloB
ThereC
ThereD
Something
would return the first four entries:
HelloA
HelloB
ThereC
ThereD
EDIT: I am using SQL92 so cannot use the left command!
Try this :
SELECT *
FROM YourTable
WHERE LEFT(stringColumn, 5) IN (
SELECT LEFT(stringColumn, 5)
FROM YOURTABLE
GROUP BY LEFT(stringColumn, 5)
HAVING COUNT(*) > 1
)
SQLFIDDLE DEMO
This selects the first 5 characters, groups by them and returns only the ones that happen more than once.
Or with Substring:
SELECT * FROM YourTable
WHERE substring(stringColumn,1,5) IN (
SELECT substring(stringColumn,1,5)
FROM YOURTABLE
GROUP BY substring(stringColumn,1,5)
HAVING COUNT(*) > 1)
;
SQLFIDDLE DEMO
Sounds easy enough...
In SQL Server this would be something along the lines of
where Left(ColumnName,5) = '12345'
Try
Select *
From tbl t1
Where exists (
Select 1
From tbl t2
Where left(t1.str, 5) = left(t2.str)
Group by left(t2.str, 5)
Having count(1) > 1
)
You didn't specify your DBMS. If it supports Windowed Aggregate functions it's:
select *
from
(
select
tab.*,
count(*) over (partition by substring(col from 1 for 5) as cnt
from tab
) as dt
where cnt > 1
You want to work with a CTE approach.
Something like this:
with CountriesCTE(Id, Name)
as (
select Id, Name from Countries
)
select distinct Countries.Name
from CountriesCTE, Countries
where left(CountriesCTE.Name,5) = left(Countries.Name,5) and CountriesCTE.Id <> Countries.Id
I need to do a query to return the next (or prev) record if a certain record is not present. For instance consider the following table:
ID (primary key) value
1 John
3 Bob
9 Mike
10 Tom.
I'd like to query a record that has id 7 or greater if 7 is not present.
My questions are,
Are these type of queries possible with SQL?
What are such queries called in the DB world?
Thanks!
Yes, it's possible, but implementation will depend on your RDBMS.
Here's what it looks like in MySQL, PostgreSQL and SQLite:
select ID, value
from YourTable
where id >= 7
order by id
limit 1
In MS SQL-Server, Sybase and MS-Access:
select top 1 ID, value
from YourTable
where id >= 7
order by id
In Oracle:
select * from (
select ID, value
from YourTable
where id >= 7
order by id
)
where rownum = 1
In Firebird and Informix:
select first 1 ID, value
from YourTable
where id >= 7
order by id
In DB/2 (this syntax is in SQL-2008 standard):
select id, value
from YourTable
where id >= 7
order by id
fetch first 1 rows only
In those RDBMS that have "window" functions (in SQL-2003 standard):
select ID, Value
from (
select
ROW_NUMBER() OVER (ORDER BY id) as rownumber,
Id, Value
from YourTable
where id >= 7
) as tmp --- remove the "as" for Oracle
where rownumber = 1
And if you are not sure which RDBMS you have:
select ID, value
from YourTable
where id =
( select min(id)
from YourTable
where id >= 7
)
Try this for MS-SQL:
SELECT TOP 1
id, value
FROM your_table
WHERE id >= 7
ORDER BY id
or for MySql
SELECT id, value
FROM your_table
WHERE id >= 7
ORDER BY id
LIMIT 0,1
I would simply do it like this:
select top 1 * from myTable where id >=7
order by id
implementation of the top 1 part is T-SQL (MSSQL/Sybase), other implementations vary but it is always possible (mysql/postgre LIMIT 1, oracle rownum = 1)
select top 1 * from Persons where Id >= #Id order by Id
In Microsoft SQL Server 2005 or above, I would like to get the first row, and if there is no matching row, then return a row with default values.
SELECT TOP 1 ID,Name
FROM TableName
UNION ALL
SELECT 0,''
ORDER BY ID DESC
This works, except that it returns two rows if there is data in the table, and 1 row if not.
I'd like it to always return 1 row.
I think it has something to do with EXISTS, but I'm not sure.
It would be something like:
SELECT TOP 1 * FROM Contact
WHERE EXISTS(select * from contact)
But if not EXISTS, then SELECT 0,''
What happens when the table is very full and you might want to specify which row of your top 1 to get, such as the first name? OMG Ponies' query will return the wrong answer in that case if you just change the ORDER BY clause. His query also costs about 8% more CPU than this modification (though it has equal reads)
SELECT TOP 1 *
FROM (
SELECT TOP 1 ID,Name
FROM TableName
ORDER BY Name
UNION ALL
SELECT 0,''
) X
ORDER BY ID DESC
The difference is that the inner query has a TOP 1 also, and which TOP 1 can be specified there (as shown).
Just for fun, this is another way to do it which performs very closely to the above query (-15ms to +30ms). While it's more complicated than necessary for such a simple query, it demonstrates a technique that I don't see other SQL folks using very often.
SELECT
ID = Coalesce(T.ID, 0),
Name = Coalesce(T.Name, '')
FROM
(SELECT 1) X (Num)
LEFT JOIN (
SELECT TOP 1 ID, Name
FROM TableName
ORDER BY ID DESC
) T ON 1 = 1 -- effective cross join but does not limit rows in the first table
Use:
SELECT TOP 1
x.id,
x.name
FROM (SELECT t.id,
t.name
FROM TABLENAME t
UNION ALL
SELECT 0,
'') x
ORDER BY id DESC
Using a CTE equivalent:
WITH query AS (
SELECT t.id,
t.name
FROM TABLENAME t
UNION ALL
SELECT 0,
'')
SELECT TOP 1
x.id,
x.name
FROM query x
ORDER BY x.id DESC
CREATE TABLE #sample(id INT, data VARCHAR(10))
SELECT TOP 1 id, data INTO #temp FROM #sample
IF ##ROWCOUNT = 0 INSERT INTO #temp VALUES (null, null)
SELECT * FROM #temp
put the top oustide of the UNION query
SELECT TOP 1 * FROM(
SELECT ID,Name
FROM TableName
UNION ALL
SELECT 0,''
) z
ORDER BY ID DESC
IF EXISTS ( SELECT TOP 1 ID, Name FROM TableName )
BEGIN
SELECT TOP 1 ID, Name FROM TableName
END
ELSE
BEGIN
--exists returned no rows
--send a default row
SELECT 0, ''
END