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
Related
(please be patient with a self-taught but fascinated beginner in postgres :)
In POSTGRES 10 I have come up with a table to track the progress in editing and archiving photo folders. This progress is measured in sequential steps, which link via foreign_key to another table that basically states 0 = "open", 1 = "work", 2 = "done". Hence I use numeric values to reference these states.
To keep the question simple here are the most important columns with some demo data:
folder_name | archive_status | step_01 | step_02 | step_03 | ...
----------------------------------------------------------------------------
john | * | 0 | 2 | 0 | ...
paul | * | 0 | 0 | 2 | ...
george | * | 2 | 1 | 0 | ...
ringo | * | 0 | 2 | 0 | ...
The desired result would be something like:
folder_name | archive_status | step_01 | step_02 | step_03 | ...
----------------------------------------------------------------------------
john | step_02 | 0 | 2 | 0 | ...
paul | step_03 | 0 | 0 | 2 | ...
george | step_01 | 2 | 1 | 0 | ...
ringo | step_02 | 0 | 2 | 0 | ...
My two problems are:
Considering my "steps" sequentially I would like to filter the "highest" ranked one (from left to right). So in the example above "john" has reached step_02", "paul has reached step_03" and so on. (Note that other values such as "george ... step_02 = 1" are irrelevant for this.)
Can't wrap my head around the way to accomplish this within the same table upon update on any of the values - would I have to use FUNCTION or VIEW or TRIGGER (or a combination of them)?
I tried approaching it with the Aggregate Functions https://www.postgresql.org/docs/10/tutorial-agg.html but I am kind of stuck, since I don't need multiple input rows, but filtering multiple columns within a row.
--- UPDATE: New problem ---
Sorry for that, but my initial demo data was not clear enough, these columns act more as a progress tracker, where in fact EACH cell within these columns could show any value. (This is where the original solution in the answer fails, since if there are two same "highest" values in a row, it will use the first occurence.) So the SQL query should find the column at the farthest to the right so to speak. Of cource I could come up with some clever "score calculations" over here, but in fact things would be so much easier with this current "matrix style" design.
So again, the desired result (archive_status) according to the values (step_xx) would be:
folder_name | archive_status | step_01 | step_02 | step_03
--------------------------------------------------------------------
john | step_02 | 2 | 2 | 0
paul | step_03 | 1 | 1 | 2
george | step_01 | 2 | 1 | 1
ringo | step_02 | 2 | 2 | 1
One option uses greatest() and a case expression:
select t.*,
case greatest(step_01, step_02, step_03)
when step_01 then 'step_01'
when step_02 then 'step_02'
when step_03 then 'step_03'
end as archive_status
from mytable t
While this would work for your current problem, I would recommend normalizing your design. Each step should be stored in a separate row rather than as a column, in a structure like (folder_name, step, status). Then you would use distinct on:
select distinct on (folder_name) t.*
from newtable t
order by folder_name, status desc, step
In addition to GMB's helpful answer above one minor change did the trick for my updated problem. This was to find out about the column "farthest to the right" in the sequence. Since the execution of CASE ... WHEN stops as soon as the first condition is met sucessfully ("true"), the trick was just to change the order of the WHEN statements. So the following code worked for me:
select t.*,
case greatest(step_01, step_02, step_03)
when step_03 then 'step_03'
when step_02 then 'step_02'
when step_01 then 'step_01'
else 'step_00'
end as archive_status
from mytable t
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.
I have a SQL Table that I'm trying to query and order the return. I am able to query just fine and the SQL Statement that I'm using is also working with the exception of the last ORDER BY statement that I need to execute. The sort order is as follows:
Sort the Status column so that 'open' is on top, 'closed' on bottom
Order the 'Flag' column so that empty (null) values are on bottom (above Status = Closed) and values on top
Order the results of items 1 and 2 by the Number column
Here is an example of the raw data:
| Flag | Number | Status |
|------------------------|
| a | 1 | open |
| | 5 | open |
| | 3 | closed |
| a | 4 | open |
| a | 2 | closed |
Here is what I'm going for:
| Flag | Number | Status |
|------------------------|
| a | 1 | open |
| a | 4 | open |
| | 5 | open |
| a | 2 | closed |
| | 3 | closed |
The query statement that I'm using is as follows:
sqlCom.CommandText = "SELECT * FROM Questions
WHERE Identifier = #identifier
AND Flag <> 'DELETED'
ORDER BY Status DESC
, (CASE WHEN Flag is null THEN 1 ELSE 0 END) ASC
, Flag DESC
, [Number] * 1 ASC";
Now, everything works fine, but the 3rd item above (sorting by Number column) doesn't work. Any ideas why?
What I'm currently getting:
| Flag | Number | Status |
|------------------------|
| a | 4 | open | <-- Out of order. Should be below the next record
| a | 1 | open | <-- Out of order. Should be one record up
| | 5 | open | <-- OK
| | 6 | open | <-- OK
| | 3 | closed | <-- OK
| a | 2 | closed | <-- OK
Thanks in advance for any helpful input. I have tried fiddling with the query in SSMS but no luck.
Your third sort expression is on Flag. Those values are being sorted alphabetically before the QNumber sort applies. And note that case matters in the ordering as well.
Here's how I would write it:
ORDER BY
Status DESC, -- might be better to use a case expression
CASE WHEN Flag IS NOT NULL THEN 0 ELSE 1 END,
QNumber
Since your data in the examples contradicts the data in the screenshot, it's not clear whether you needed to remove the third sort column entirely or just sort by ignoring the case of the text.
I'm new to Hive/SQL, and I'm stuck on a fairly simple problem. My data looks like:
+------------+--------------------+-----------------------+
| carrier_iD | meandelay | meancanceled |
+------------+--------------------+-----------------------+
| EV | 13.795802119653473 | 0.028584251044292006 |
| VX | 0.450591016548463 | 2.364066193853424E-4 |
| F9 | 10.898001378359766 | 0.00206753962784287 |
| AS | 0.5071547420965062 | 0.0057404326123128135 |
| HA | 1.2031093279839498 | 5.015045135406214E-4 |
| 9E | 8.147899230704216 | 0.03876067292247866 |
| B6 | 9.45383857757506 | 0.003162096314343487 |
| UA | 8.101511665305816 | 0.005467725574605967 |
| FL | 0.7265068895709532 | 0.0041141513746490044 |
| WN | 7.156119279121648 | 0.0057419058192869415 |
| DL | 4.206288692245839 | 0.005123990066804269 |
| YV | 6.316802855264404 | 0.029304029304029346 |
| US | 3.2221527095063736 | 0.007984031936127766 |
| OO | 6.954715814690328 | 0.02596499362466706 |
| MQ | 9.74568222216328 | 0.025628100708354324 |
| AA | 8.720522654298968 | 0.019242775597574157 |
+------------+--------------------+-----------------------+
I want Hive to return the row with the meanDelay max value. I have:
SELECT CAST(MAX(meandelay) as FLOAT) FROM flightinfo;
which indeed returns the max (I use cast because my values are saved as STRING). So then:
SELECT * FROM flightinfo WHERE meandelay = (SELECT CAST(MAX(meandelay) AS FLOAT) FROM flightinfo);
I get the following error:
FAILED: ParseException line 1:44 cannot recognize input near 'select' 'cast' '(' in expression specification
Use the windowing and analytics functions
SELECT carrier_id, meandelay, meancanceled
FROM
(SELECT carrier_id, meandelay, meancanceled,
rank() over (order by cast(meandelay as float) desc) as r
FROM table) S
WHERE S.r = 1;
This will also solve the problem if more than one row has the same max value, you'll get all the rows as result. If you just want a single row change rank() to row_number() or add another term to the order by.
use join instead.
SELECT a.* FROM flightinfo a left semi join
(SELECT CAST(MAX(meandelay) AS FLOAT)
maxdelay FROM flightinfo)b on (a.meandelay=b.maxdelay)
You can use the collect_max UDF from Brickhouse ( http://github.com/klout/brickhouse ) to solve this problem, passing in a value of 1, meaning that you only want the single max value.
select array_index( map_keys( collect_max( carrier_id, meandelay, 1) ), 0 ) from flightinfo;
Also, I've read somewhere that the Hive max UDF does allow you to access other fields on the row, but I think its easier just to use collect_max.
I don't think your sub-query is allowed ...
A quick look here:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SubQueries
states:
As of Hive 0.13 some types of subqueries are supported in the WHERE
clause. Those are queries where the result of the query can be treated
as a constant for IN and NOT IN statements (called uncorrelated
subqueries because the subquery does not reference columns from the
parent query):
I'm sure this has been asked but I can't quite find the right search terms.
Given a schema like this:
| CarMakeID | CarMake
------------------------
| 1 | SuperCars
| 2 | MehCars
| CarMakeID | CarModelID | CarModel
-----------------------------------------
| 1 | 1 | Zoom
| 2 | 1 | Wow
| 3 | 1 | Awesome
| 4 | 2 | Mediocrity
| 5 | 2 | YoureSettling
I want to produce a dataset like this:
| CarMakeID | CarMake | CarModels
---------------------------------------------
| 1 | SuperCars | Zoom, Wow, Awesome
| 2 | MehCars | Mediocrity, YoureSettling
What do I do in place of 'AGG' for strings in SQL Server in the following style query?
SELECT *,
(SELECT AGG(CarModel)
FROM CarModels model
WHERE model.CarMakeID = make.CarMakeID
GROUP BY make.CarMakeID) as CarMakes
FROM CarMakes make
http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/
It is an interesting problem in Transact SQL, for which there are a number of solutions and considerable debate. How do you go about producing a summary result in which a distinguishing column from each row in each particular category is listed in a 'aggregate' column? A simple, and intuitive way of displaying data is surprisingly difficult to achieve. Anith Sen gives a summary of different ways, and offers words of caution over the one you choose...
If it is SQL Server 2017 or SQL Server VNext, Azure SQL database you can use String_agg as below:
SELECT make.CarMakeId, make.CarMake,
CarModels = string_agg(model.CarModel, ', ')
FROM CarModels model
INNER JOIN CarMakes make
ON model.CarMakeId = make.CarMakeId
GROUP BY make.CarMakeId, make.CarMake
Output:
+-----------+-----------+---------------------------+
| CarMakeId | CarMake | CarModels |
+-----------+-----------+---------------------------+
| 1 | SuperCars | Zoom, Wow, Awesome |
| 2 | MehCars | Mediocrity, YoureSettling |
+-----------+-----------+---------------------------+