I'm trying to filter a queryset on the first characters of an element in an ArrayField in postgresql.
Data
--------------------
| id | registration_date | sbi_codes |
| 1 | 2007-11-13 | {9002, 1002, 85621} |
| 2 | 2010-10-11 | {1002, 9022, 9033 |
| 3 | 2019-02-02 | {9001, 8921} |
| 4 | 2012-02-02 | {120} |
I've tried the following (which obviously don't work), but I think clearly indicates what I'm trying to achieve.
select count(*)
from administrations_administration
where '90' = left(any(sbi_codes),2)
or
select count(*)
from administrations_administration
where '90%' like any(sbi_codes
So the sbi_codes can be for example 9002 or 9045, And I'm trying to filter all the records that contain an element that starts with 90.
expected result
____
| count | sbi_codes |
| 3 | 90 |
Thanks!
The thing on the left hand side of LIKE is the string, in which % is just a %. The thing on the right hand side is the pattern, in which % is a wildcard. Using ANY does't change these semantics, the pattern still goes the right.
To solve this, you could create your own operator which is like LIKE, but has its arguments reversed.
Related
I have a table with the following structure and data in it:
| ID | Date | Result |
|---- |------------ |-------- |
| 1 | 30/04/2020 | + |
| 1 | 01/05/2020 | - |
| 1 | 05/05/2020 | - |
| 2 | 03/05/2020 | - |
| 2 | 04/05/2020 | + |
| 2 | 05/05/2020 | - |
| 2 | 06/05/2020 | - |
| 3 | 01/05/2020 | - |
| 3 | 02/05/2020 | - |
| 3 | 03/05/2020 | - |
| 3 | 04/05/2020 | - |
I'm trying to write an SQL query (I'm using SQL Server) which returns the date of the first two consecutive negative results for a given ID.
For example, for ID no. 1, the first two consecutive negative results are on 01/05 and 05/05.
The first two consecutive results for ID No. 2 are on 05/05 and 06/05.
The first two consecutive negative results for ID No. 3 are on on 01/05 and 02/05 .
So the query should produce the following result:
| ID | FirstNegativeDate |
|---- |------------------- |
| 1 | 01/05 |
| 2 | 05/05 |
| 3 | 01/05 |
Please note that the dates aren't necessarily one day apart. Sometimes, two consecutive negative tests may be several days apart. But they should still be considered as "consecutive negative tests". In other words, two negative tests are not 'consecutive' only if there is a positive test result in between them.
How can this be done in SQL? I've done some reading and it looks like maybe the PARTITION BY statement is required but I'm not sure how it works.
This is a gaps-and-island problem, where you want the start of the first island of '-'s that contains at least two rows.
I would recommend lead() and aggregation:
select id, min(date) first_negative_date
from (
select t.*, lead(result) over(partition by id order by date) lead_result
from mytable t
) t
where result = '-' and lead_result = '-'
group by id
Use LEAD or LAG functions over ID partition ordered by your Date column.
Then simple check where LEAD/LAG column is equal to Result.
You'll need also to filter the top ones.
The image attached just shows what LEAD/LAG would return
I have a table (e.g. Users) in PostgreSQL database. Its size is relatively large (ca. 4 GB of data) and I would like to get a table/result consisting of single rows fulfilling the select query. This query shall be executed for each element in an array of strings (couple dozens of elements).
Example single select for one element:
SELECT * FROM "Users" WHERE "Surname" LIKE 'Smith%' LIMIT 1
Value between ' and %' should be an element of input array.
EDIT: It doesn't matter for me whether I get record no. 1 or 2 for LIKE 'Smith%'
How can I achieve this?
I tried to append query results to some array variable within FOREACH loop but with no success.
Example source table:
| Id | Name | Surname |
|---- |-------- |---------- |
| 1 | John | Smiths |
| 2 | Adam | Smith |
| 3 | George | Kowalsky |
| 4 | George | Kowalsky |
| 5 | Susan | Connor |
| 6 | Clare | Connory |
| 7 | Susan | Connor |
And for ['Smith', 'Connor'] the output is:
| Id | Name | Surname |
|----|-------|---------|
| 1 | John | Smiths |
| 5 | Susan | Connor |
In Postgres you can use the ANY operator to compare a single value to all values of an array. This also works with together with the LIKE operator.
SELECT *
FROM "Users"
WHERE "Surname" like ANY (array['Smith%', 'Connor%'])
Note that LIKE is case sensitive, if you don't want that, you can use ILIKE
This will show you the logic. Syntax is up to you.
where 1 = 2
start of loop
or surname like 'Array Element goes here%'
end of loop
I'm working on an old SQL Server database that has several tables that look like the following:
|-------------|-----------|-------|------------|------------|-----|
| MachineName | AlarmName | Event | AlarmValue | SampleTime | ... |
|-------------|-----------|-------|------------|------------|-----|
| 3 | 180 | 8 | 6.780 | 2014-02-24 | |
| 9 | 67 | 8 | 1.45 | 2014-02-25 | |
| ... | | | | | |
|-------------|-----------|-------|------------|------------|-----|
There is a separate table in the database that only contains unique strings, as well as the index for each unique string. The unique string table looks like this:
|----------|--------------------------------|
| Id | String |
|----------|--------------------------------|
| 3 | MyMachine |
| ... | |
| 8 | High CPU Usage |
| ... | |
| 67 | 404 Error |
| ... | |
|----------|--------------------------------|
Thus, when we want to get something out of the database, we get the respective rows out, then lookup each missing string based on the index value.
What I'm hoping to do is to replace all of the string indexes with the actual values in a single query without having to do post-processing on the query result.
However, I can't figure out how to do this in a single query. Do I need to use multiple JOINs? I've only been able to figure out how to replace a single value by doing something like -
SELECT UniqueString.String AS "MachineName" FROM UniqueString
JOIN Alarm ON Alarm.MachineName = UniqueString.Id
Any help would be much appreciated!
Yes, you can do multiple joins to the UniqueStrings table, but change the order to start with the table you are reporting on and use unique aliases for the joined table. Something like:
SELECT MN.String AS 'MachineName', AN.String as 'AlarmName' FROM Alarm A
JOIN UniqueString MN ON A.MachineName = MN.Id
JOIN UniqueString AN ON A.AlarmName = AN.Id
etc for any other columns
I'm kinda confused on how this thing can be done.
I have a database table having these values:
| id | file_type | code | position |
-------------------------------------
| 1 | Order | SO | 1 |
| 2 | Order | 1-SO | 7 |
| 3 | Order | 1_SO | 7 |
Now, I want to get the position and the file type of my filename so I come up with this query:
SET #FileName = '1-SO1234567890.pdf'
SELECT *
FROM tbl_FileTypes
WHERE CHARINDEX(code,#FileName)> 0
Sadly, I'm getting two results here, I only need the data with the "1-SO" result.
| id | file_type | code | position |
-------------------------------------
| 1 | Order | SO | 1 |
| 2 | Order | 1-SO | 7 |
I believe that my WHERE Clause causes this to happen.
Is there any better way for me to get my desired results?
Thank you very much in advance.
You might want to use SUBSTRING instead (assuming T-SQL):
WHERE code = SUBSTRING(#FileName,1, LEN(code));
Which checks if the first n-chars of FileName equal a given code.
DEMO
well
SET #FileName = '1-SO1234567890.pdf'
SELECT *
FROM tbl_FileTypes
WHERE CHARINDEX(code,#FileName) = 1
would work in this case but if you had a code '1-SOS' it's going to fail again.
Since you are cheking left most characters, you could also use LEFT() function as below. Also use TOP (1) to get a single record and consider ordering as needed.
SELECT TOP (1) *
FROM tbl_FileTypes
WHERE LEFT(#FileName,LEN(code)) = code
--ORDER BY yourCol
Thankfully, I haven't had to work with particularly complex SQL queries before. Here's my goal.
I have the table hams, which I would like to cross-join with the table eggs - that is, get all ham-egg combinations... to an extent.
The eggs table also has an attribute how_cooked, which is defined as ENUM('over-easy','scrambled','poached'). I would like a resultset listing every possible combination of ham and egg-cooking method, along with a sample egg cooked that way. (I don't care which egg in particular.)
So if 3 hams with id of 1, 2, and 3, and 3 eggs of each cooking method, my resultset should look something like this:
+---------+-----------------+---------+
| hams.id | eggs.how_cooked | eggs.id |
+---------+-----------------+---------+
| 1 | over-easy | 1 |
| 1 | scrambled | 4 |
| 1 | poached | 7 |
| 2 | over-easy | 1 |
| 2 | scrambled | 4 |
| 2 | poached | 7 |
| 3 | over-easy | 1 |
| 3 | scrambled | 4 |
| 3 | poached | 7 |
+---------+-----------------+---------+
I'm sure I could hack together some solution with loads of subqueries here and there, but is there any elegant way to do this is MySQL?
Through a bit of thinking real hard and Googling, I may have found a good solution:
SELECT * FROM hams, eggs GROUP BY hams.id, eggs.how_cooked
It seems to work. Is it really that easy?
SELECT hams.id, eggs.how_cooked, eggs.id
FROM hams
CROSS JOIN eggs
This does the trick. CROSS JOIN is synonymous with , but has a higher precedence in MySQL .
MySQL 5.0 Reference - JOIN syntax