SQL select two nearly fields - sql

How do I select two most nearly fields to specific timestamp?
SELECT *
FROM 'wp_weather'
WHERE ( timestamp most nearly to 1385435000) AND city = 'Махачкала'
The table:
id | timestamp
---------------
0 | 1385410000
1 | 1385420000
2 | 1385430000
3 | 1385440000
4 | 1385450000

SELECT *
FROM wp_weather
WHERE city = 'Махачкала'
order by abs(timestamp - 1385435000)
limit 2

You may try like this:
SELECT * FROM 'wp_weather'
WHERE city = 'Махачкала'
order by abs(timestamp - 1385435000)
limit 2
Also check the ABS function

Related

how to use sql where condition on comma separated value

| id | name | numbers |
+----+---------+----------------+
| 1 | arjun | 62,45,68,95,50 |
| 2 | yuvaraj | 45,65,85,68 |
| 3 | sahadev | 45,65,85,68 |
| 4 | yogi | 45,65,85,68 |
| 5 | krishna | 45,65,85,68 |
I want id data where number is 45
I tried
select *
from table
where number=45
but it doesn't work.
With like:
select * from table where concat(',', numbers, ',') like concat('%,', '45',',%')
because you need to transform the column's value to something like this:
,45,65,85,68,
and then apply like to the pattern '%,45,%'.
You can try using like operator
select * from table where number like '%45%'
or you can use find_in_set() for mysql database
select * from table where find_in_set(45,number)>0
using like operator with pattern as '%45%':
select * from table where numbers like '%45%'
For Postgres you can use:
select *
from the_table
where '45' = any(string_to_array(numbers, ','));
If you use like operator it will get all the records having 45 (like 345 or 12245 or 65445). if you want records having values exactly "45" You can try the below code if you are using SQL Server 2016 or higher versions.
select * from (
SELECT * FROM tablename
cross apply
STRING_SPLIT('numbers',',') )a where value='45'

Counting the total number of rows with SELECT DISTINCT ON without using a subquery

I have performing some queries using PostgreSQL SELECT DISTINCT ON syntax. I would like to have the query return the total number of rows alongside with every result row.
Assume I have a table my_table like the following:
CREATE TABLE my_table(
id int,
my_field text,
id_reference bigint
);
I then have a couple of values:
id | my_field | id_reference
----+----------+--------------
1 | a | 1
1 | b | 2
2 | a | 3
2 | c | 4
3 | x | 5
Basically my_table contains some versioned data. The id_reference is a reference to a global version of the database. Every change to the database will increase the global version number and changes will always add new rows to the tables (instead of updating/deleting values) and they will insert the new version number.
My goal is to perform a query that will only retrieve the latest values in the table, alongside with the total number of rows.
For example, in the above case I would like to retrieve the following output:
| total | id | my_field | id_reference |
+-------+----+----------+--------------+
| 3 | 1 | b | 2 |
+-------+----+----------+--------------+
| 3 | 2 | c | 4 |
+-------+----+----------+--------------+
| 3 | 3 | x | 5 |
+-------+----+----------+--------------+
My attemp is the following:
select distinct on (id)
count(*) over () as total,
*
from my_table
order by id, id_reference desc
This returns almost the correct output, except that total is the number of rows in my_table instead of being the number of rows of the resulting query:
total | id | my_field | id_reference
-------+----+----------+--------------
5 | 1 | b | 2
5 | 2 | c | 4
5 | 3 | x | 5
(3 rows)
As you can see it has 5 instead of the expected 3.
I can fix this by using a subquery and count as an aggregate function:
with my_values as (
select distinct on (id)
*
from my_table
order by id, id_reference desc
)
select count(*) over (), * from my_values
Which produces my expected output.
My question: is there a way to avoid using this subquery and have something similar to count(*) over () return the result I want?
You are looking at my_table 3 ways:
to find the latest id_reference for each id
to find my_field for the latest id_reference for each id
to count the distinct number of ids in the table
I therefore prefer this solution:
select
c.id_count as total,
a.id,
a.my_field,
b.max_id_reference
from
my_table a
join
(
select
id,
max(id_reference) as max_id_reference
from
my_table
group by
id
) b
on
a.id = b.id and
a.id_reference = b.max_id_reference
join
(
select
count(distinct id) as id_count
from
my_table
) c
on true;
This is a bit longer (especially the long thin way I write SQL) but it makes it clear what is happening. If you come back to it in a few months time (somebody usually does) then it will take less time to understand what is going on.
The "on true" at the end is a deliberate cartesian product because there can only ever be exactly one result from the subquery "c" and you do want a cartesian product with that.
There is nothing necessarily wrong with subqueries.

Select and count in the same query on two tables

I've got these two tables:
___Subscriptions
|--------|--------------------|--------------|
| SUB_Id | SUB_HotelId | SUB_PlanName |
|--------|--------------------|--------------|
| 1 | cus_AjGG401e9a840D | Free |
|--------|--------------------|--------------|
___Rooms
|--------|-------------------|
| ROO_Id | ROO_HotelId |
|--------|-------------------|
| 1 |cus_AjGG401e9a840D |
| 2 |cus_AjGG401e9a840D |
| 3 |cus_AjGG401e9a840D |
| 4 |cus_AjGG401e9a840D |
|--------|-------------------|
I'd like to select the SUB_PlanName and count the rooms with the same HotelId.
So I tried:
SELECT COUNT(*) as 'ROO_Count', SUB_PlanName
FROM ___Rooms
JOIN ___Subscriptions
ON ___Subscriptions.SUB_HotelId = ___Rooms.ROO_HotelId
WHERE ROO_HotelId = 'cus_AjGG401e9a840D'
and
SELECT
SUB_PlanName,
(
SELECT Count(ROO_Id)
FROM ___Rooms
Where ___Rooms.ROO_HotelId = ___Subscriptions.SUB_HotelId
) as ROO_Count
FROM ___Subscriptions
WHERE SUB_HotelId = 'cus_AjGG401e9a840D'
But I get empty datas.
Could you please help ?
Thanks.
You need to use GROUP BY whenever you do some aggregation(here COUNT()). Below query will give you the number of ROO_ID only for the SUB_HotelId = 'cus_AjGG401e9a840D' because you have this condition in WHERE. If you want the COUNTs for all Hotel_IDs then you can simply remove the WHERE filter from this query.
SELECT s.SUB_PlanName, COUNT(*) as 'ROO_Count'
FROM ___Rooms r
JOIN ___Subscriptions s
ON s.SUB_HotelId = r.ROO_HotelId
WHERE r.ROO_HotelId = 'cus_AjGG401e9a840D'
GROUP BY s.SUB_PlanName;
To be safe, you can also use COUNT(DISTINCT r.ROO_Id) if you don't want to double count a repeating ROO_Id. But your table structures seem to have unique(non-repeating) ROO_Ids so using a COUNT(*) should work as well.

How to search max value from group in sql

I am just learning some SQL, so I have a question.
-I have a table with name TABL
-a variable :ccname which has a value "Bottle"
The table is as follows:
+----------+---------+-------+--------+
| Name | Price | QTY | CODE |
+----------+---------+-------+--------+
| Rope | 3.6 | 35 | 236 |
| Chain | 2.8 | 15 | 237 |
| Paper | 1.6 | 45 | 124 |
| Bottle | 4.5 | 41 | 478 |
| Bottle | 1.8 | 12 | 123 |
| Computer | 1450.75 | 71 | 784 |
| Spoon | 0.7 | 10 | 412 |
| Bottle | 1.3 | 15 | 781 |
| Rope | 0.9 | 14 | 965 |
+----------+---------+-------+--------+
Now I want to find the CODE from the variable :ccname with the higher quantity! So I translated like this:
SELECT CODE
FROM TABL
GROUP BY :ccname
WHERE QTY=MAX(QTY)
In a perfect world that would turn as a result 478.
In the SQL world what should I write in order to get 478?
You probably want something like that:
SELECT code
FROM TABL
WHERE Name=:ccname
ORDER BY QTY DESC
LIMIT 1
The idea is we find all rows of the table whose Name column is the same as the contents of the variable :ccname, then order them by the quantity in descending order, and filally we select first one, which has to be the one with the largest quantity because they are sorted in descending order.
Try this
SELECT CODE
FROM TABLENAme
WHERE QTY = (SELECT MAX(QTY) FROM TablName WHERE Name = :ccname)
Use ORDER BY, a proper WHERE, and the something to limit the result set to one row:
SELECT CODE
FROM TABL
WHERE name = :ccname
ORDER BY QTY DESC
FETCH FIRST 1 ROW ONLY;
Note: Some databases spell the ANSI standard FETCH FIRST 1 ROW ONLY as LIMIT or as SELECT TOP 1.
Depending on your specific database, you can use one of the following options to restrict your result set to a single value after ordering your existing columns through an ORDER BY clause:
SELECT TOP 1
LIMIT 1
FETCH FIRST 1 ROW ONLY
Syntax Examples
SELECT TOP 1 Code
FROM TABL
WHERE Name = :ccname
ORDER BY QTY DESC
or
SELECT Code
FROM TABL
WHERE Name = :ccname
ORDER BY QTY DESC
LIMIT 1
or
SELECT CODE
FROM TABL
WHERE Name = :ccname
ORDER BY QTY DESC
FETCH FIRST 1 ROW ONLY;
Using join can also effectively solve the question:
Select t1.Code
From TABL As t1 Join (
Select Name, Max(table.QTY) as MaxQTY
From TABL
Where Name = :ccname
Group by Name
) As t2
Where t1.QTY = t2.MaxQTY And t1.Name = t2.Name
Explanation:
You first calculate the maximum value for "Bottle" using the subquery and then join the two tables to select corresponding row with MaxQTY and same name.

Search an SQL table that already contains wildcards?

I have a table that contains patters for phone numbers, where x can match any digit.
+----+--------------+----------------------+
| ID | phone_number | phone_number_type_id |
+----+--------------+----------------------+
| 1 | 1234x000x | 1 |
| 2 | 87654311100x | 4 |
| 3 | x111x222x | 6 |
+----+--------------+----------------------+
Now, I might have 511132228 which will match with row 3 and it should return its type. So, it's kind of like SQL wilcards, but the other way around and I'm confused on how to achieve this.
Give this a go:
select * from my_table
where '511132228' like replace(phone_number, 'x', '_')
select *
from yourtable
where '511132228' like (replace(phone_number, 'x','_'))
Try below query:
SELECT ID,phone_number,phone_number_type_id
FROM TableName
WHERE '511132228' LIKE REPLACE(phone_number,'x','_');
Query with test data:
With TableName as
(
SELECT 3 ID, 'x111x222x' phone_number, 6 phone_number_type_id from dual
)
SELECT 'true' value_available
FROM TableName
WHERE '511132228' LIKE REPLACE(phone_number,'x','_');
The above query will return data if pattern match is available and will not return any row if no match is available.