Bringing back multiple max on a single column in sql - sql

I have a spreadsheet with customer accounts and when we get a new account it gets added on using a reference account number i.e. Anderson Electrical would be AND01 etc. I'm trying to use sql to bring back the highest number from each variation of letterings e.g. if AND01 already existed and our highest company value was AND34 then it would just bring back AND34 rather than 1 to 34.
Each account has the first 3 letters of there company name followed by whatever the next number is.
Hope I have explained this well enouh for someone to understand :)

For a single reference account:
select max(AcctNum)
from Accounts
where left(AcctNum, 3) = <reference account>
If you want it for all at once:
select left(AcctNum, 3) as ReferenceAcct, max(AcctNum)
from Accounts
group by left(AcctNum, 3)

Not sure if that's what you're asking but if you need to find max value that is part of a string you can do it with substring. So if you need to find the highest number from a column that contains those values you can do it with:
;WITH tmp AS(
SELECT 'AND01' AS Tmp
UNION ALL
SELECT 'AND34'
) SELECT MAX(SUBSTRING(tmp, 4, 2)) FROM tmp GROUP BY SUBSTRING(tmp, 0, 3)
That's a little test query that returns 34 because I'm grouping by first 3 letters, you probably want to group it by some ID.

Related

Count instances within a date range in AWS Athena

Trying to query my table to tell me the count of instances of one of my columns appearing over 2 different ETL runs. How I would ask it to give me everything in regards to its harmonized value is
SELECT clientname, mdm_cleanse_value_clientname FROM "tablename" WHERE mdm_cleansed_value_clientname IS NULL
That would give me what is left to harmonize. Im interested in duplicate values appearing across the next batch, we use metadata_job_start_time as our indicator, so I would need either a TOP or MAX function that includes the top 2 metadata_job_start_time
I am imagining towards the end it would read
SELECT metadata_job_run_id, metadata_job_start_time, clientname, COUNT(clientname)
FROM "tablename"
WHERE COUNT(clientname) > 1
GROUP BY metadata_job_start_time, metadata_job_run_id, clientname
How do I put in my date range

How to count unique occurences of string in table for separate records in apex 5

I am trying to automatically count the unique occurrences of a string saved in the table. Currently I have a count of a string but only when a user selects the string and it gives every record the same count value.
For example
Below is a image of my current table:
From the image you can see that there is a Requirement column and a count column. I have got it to the point were when the user would select a requirement record (each requirement record has a link) it would insert the requirement text into a requirement item called 'P33_REQUIREMENT' so the count can have a value to compare to.
This is the SQL that I have at current:
SELECT (SELECT COUNT(*)
FROM DIA_ASSOCIATED_QMS_DOCUMENTS
WHERE REQUIREMENT = :P33_REQUIREMENT
group by REQUIREMENT
) AS COUNT,
DPD.DIA_SELECTED,
DPD.Q_NUMBER_SELECTED,
DPD.SECTION_SELECTED,
DPD.ASSIGNED_TO_PERSON,
DAQD.REFERENCE,
DAQD.REQUIREMENT,
DAQD.PROGRESS,
DAQD.ACTION_DUE_DATE,
DAQD.COMPLETION_DATE,
DAQD.DIA_REF,
DA.DIA,
DA.ORG_RISK_SCORE
FROM DIA_PROPOSED_DETAIL DPD,
DIA_ASSOCIATED_QMS_DOCUMENTS DAQD,
DIA_ASSESSMENTS DA
WHERE DPD.DIA_SELECTED = DAQD.DIA_REF
AND DPD.DIA_SELECTED = DA.DIA
This is the sql used to make the table in the image.
This issue with this is, it is giving every record the same count when the user selects a requirement value. I can kind of fix this by also adding in AND DIA_SELECTED = :P33_DIA into the where clause of the count. DIA_SELECTED being the first column in the table and :P33_DIA being the item that stores the DIA ref number relating to the record chosen.
The output of this looks like:
As you can see there is only one count. Still doesn't fix the entire issue but a bit better.
So to sum up is there a way to have the count, count the occurrences individually and insert them in the requirements that are the same. So if there are three tests like in the images there would be a '3' in the count column where requirement = 'test', and if there is one record with 'test the system' there would be a '1' in the count column.
Also for more context I wont know what the user will input into the requirement so I can't compare to pre-determined strings.
I'm new to stack overflow I am hoping I have explained enough and its not too confusing.
The following extract:
SELECT (SELECT COUNT(*)
FROM DIA_ASSOCIATED_QMS_DOCUMENTS
WHERE REQUIREMENT = :P33_REQUIREMENT group by REQUIREMENT ) AS COUNT
Could be replaced by
SELECT (SELECT COUNT(*)
FROM DIA_ASSOCIATED_QMS_DOCUMENTS
WHERE REQUIREMENT = DAQD.REQUIREMENT ) AS COUNT
Which would give you - for each line, the number of requirements that are identical.
I'm not completely certain it is what you are after, but if it isn't, it should give you some ideas on how to progress (or allow you to indicate where I failed to understand your request)

Identify the last occurance of a subsring in a string, where the substring is from a table. Teradata

I have the following problem:
I need to identify the last occurrence of any sub-string given in table A, and return that given value in return in the select statement of another statement. This is a bit convoluted, but here is the code:
SELECT TRIM(COUNTRY_CODE)
FROM (
SELECT TOP 1 POSITION( PHRASE IN MY_STRING) AS PHRASE_LOCATION, CODE
FROM REFERENCE_TABLE -- Where the country list is located
WHERE PHRASE_LOCATION > 0 -- To return NULL if there is no matches
ORDER BY 1 DESC -- To get the last one
) t1
This works when run by it self, but i have large problems getting it to work as part of another queries' select. I need "MY_STRING" to come from a higher level in the nested select three. The reasons for this is how the system is designed on a higher level.
In other words i need the following:
PHRASE is coming from a table that have a phrases and a code associated
MY_STRING is used in the higher level select and i need to associate a code with it, based on the last occurring phrase
Number of different phrases > 400 so no hard coding :(
Number of different "MY_STRING" > 1 000 000 / day
So far i tried what you can see above, but due to the constraints of the system, i cannot be to creative.
Example Phrases: "New York", "London", "Oslo"
Example Codes: "US", "UK, "NO"
Example Strings: "London House, Something street, New York"; "Some street x, 0120, OSL0".
Desired Outcomes: "US"; "NO"
This will result in a product join, i.e. use a lot of CPU:
SELECT MY_STRING
-- using INSTR searching the last occurance instead of POSITION if the same PHRASE might occur multiple times
-- INSTR is case sensitive -> must use LOWER
,Instr(Lower(MY_STRING), Lower(PHRASE), -1, 1) AS PHRASE_LOCATION
,CODE
,PHRASE
FROM table_with_MY_STRING
LEFT JOIN REFERENCE_TABLE -- to return NULL if no match
ON PHRASE_LOCATION > 0
QUALIFY
Row_Number() -- return last match
Over (PARTITION BY MY_STRING
ORDER BY PHRASE_LOCATION DESC) = 1
If this is not efficient enough another possible solution might utilize STRTOK_SPLIT_TO_TABLE/REGEXP_SPLIT_TO_TABLE: split the address into parts and then join those parts to PHRASE.

need to look through many records of one table for each one in another

In Oracle SQL Developer, I get the error, "ORA-01427: single-row subquery returns more than one row" when I try to run this line of code.
UPDATE stream_log sl
set recordnum =
(SELECT recordnum
FROM STREAM_LOG_HISTORY slh
WHERE substr(slh.recordnum, 2, 5) = sl.recordnum);
In order to try to fix it, I tried changing my code to this:
UPDATE stream_log sl
set recordnum =
(SELECT recordnum
FROM STREAM_LOG_HISTORY slh
WHERE substr(slh.recordnum, 2, 5) = sl.recordnum).first;
but it says the period is syntactically erroneous.
I need to retrieve the first character of strings that match the last 5 of the given one, but to do that I need to look through many records of one table for each one in another. Any advice is appreciated.
I need to retrieve the first character of strings that match the last
5 of the given one,
The "first character" that matches cannot be guaranteed to be a particular string, every time you run the update, unless you have any other unique column which could be used to order the results, preferably using row_number() or FIRST_VALUE functions. So, other option is to use MAX or MIN to get a single record for each match.
UPDATE stream_log sl
SET recordnum = (
SELECT MAX(recordnum)
FROM stream_log_history slh
WHERE Substr(slh.recordnum, 2, 5) = sl.recordnum
);

Create a Counter that resets with every change in name

This site has been a great resource for me over the years but I finally ran into an issue i couldn't find a solution for already posted.
I have a list of names, dates and values. I need to turn the dates into the numbers and for them to start over for each well where value is greater than 0.
My thought was to create a loop but I'm short on skills to make it happen.
I found a post to create the counter but not how to loop it:
SELECT Name, row_number() over (order by (select NULL))
FROM [$ST_MASTER]
The Yellow Column Is What I Want to Create
You're in the right direction. Your over by need to change in two ways:
1) You need to restart the row number with each name.
2) You need to restart the row number when the value becomes zero.
After this, we just need to discard the row numbers for zero quantity rows. You'll see I did this by using the ZeroOnePartSort value.
One flow in this logic: This assumes (per your data sample) that once quantities go positive for a name, they don't go to zero again.
WITH ValSort AS (
SELECT Name, CASE WHEN value = 0 THEN 0 ELSE 1 END AS ZeroOnePart,
DateStamp, Value FROM dbo.STMaster
)
SELECT vs.Name, vs.DateStamp, vs.Value,
ROW_NUMBER() OVER(PARTITION BY vs.Name, vs.ZeroOnePart
ORDER BY vs.DateStamp) * vs.ZeroOnePart
FROM ValSort vs