Selecting distinct substring values - tsql

I have a field that is similar to a MAC address in that the first part is a group ID and the second part is a serial number. My field is alphanumeric and 5 digits in length, and the first 3 are the group ID.
I need a query that gives me all distinct group IDs and the first serial number lexicographically. Here is sample data:
ID
-----
X4MCC
X4MEE
X4MFF
V21DD
8Z6BB
8Z6FF
Desired Output:
ID
-----
X4MCC
V21DD
8Z6BB
I know I can do SELECT DISTINCT SUBSTRING(ID, 1, 3) but I don't know how to get the first one lexicographically.

Another way which seems to have the same cost as the query by gbn:
SELECT MIN(id)
FROM your_table
GROUP BY SUBSTRING(id, 1, 3);

SELECT
ID
FROM
(
SELECT
ID,
ROW_NUMBER() OVER (PARTITION BY SUBSTRING(ID, 1, 3) ORDER BY ID) AS rn
FROM MyTable
) oops
WHERE
rn = 1

Related

how to list records that conform to a sequentially incrementing id in postgres

Is there a way to select records are sequentially incremented?
for example, for a list of records
id 0
id 1
id 3
id 4
id 5
id 8
a command like:
select id incrementally from 3
Will return values 3,4 and 5. It won't return 8 because it's not sequentially incrementing from 5.
step-by-step demo:db<>fiddle
WITH groups AS ( -- 2
SELECT
*,
id - row_number() OVER (ORDER BY id) as group_id -- 1
FROM mytable
)
SELECT
*
FROM groups
WHERE group_id = ( -- 4
SELECT group_id FROM groups WHERE id = 3 -- 3
)
row_number() window function create a consecutive row count. With this difference you are able to create groups of consecutive records (id values which are increasing by 1)
This query is put into a WITH clause because we reuse the result twice in the next step
Select the recently created group_id
Filter the table for this group.
Additionally: If you want to start your output at id = 4, for example, you need to add a AND id >= 4 filter to the WHERE clause

SQL query to put a number in a column and put an incremented number when there is a new text in a column

I have a query SELECT * from TABLE which gives the result as below table:
Expected column is as below:
I want to frame a new column like whenever we get the value as 0 then the number should be incremented by 1. I tried DENSE_RANK() , ROW_NUMBER() but couldn't get the exact result which mentioned. Is that possible in PostgreSQL.
Try This:
select name, value,
sum(case when value=0 then 1 else 0 end) over (order by "sno")
from (
select row_number() over() as "sno",* from example
) tab
DEMO
NOTE: Please note that there is no guaranteed that you will get same output always due no ordering field in your raw data.
So Better approach is to add some field in your view output by which it can be ordered and run the query like below:(assuming you have a ID field)
select
name,
value,
sum(case when value=0 then 1 else 0 end) over (order by id)
from example
DEMO

select row number for given record id with postgres row_number() function

Sry, if my question isn't new but i can't find answer. I want to find row number for given id in postgres table.I have the folowing Postgres query
"SELECT row_number() over (ORDER BY id DESC) FROM
(SELECT id, row_number() over () FROM user ORDER BY id DESC) AS sub
WHERE id = ?1"
?1 - user id
This query always return 1 for any user id, but i need that it return actual record row number. For example, if i have 50 records in my database with ids from 1 to 50 and i execute query with id = 30, i want to retun row_number = 30. Thanks in advance.
If I followed you correctly, you could just use an aggregate query:
select count(*) rn
from user
where id <= ?1
This counts how many records have an id that is smaller (or equal) to the given parameter.

Retrieving Representative Records for Unique Values of Single Column

For Postgresql 8.x, I have an answers table containing (id, user_id, question_id, choice) where choice is a string value. I need a query that will return a set of records (all columns returned) for all unique choice values. What I'm looking for is a single representative record for each unique choice. I also want to have an aggregate votes column that is a count() of the number of records matching each unique choice accompanying each record. I want to force choice to lowercase for this comparison to be made (HeLLo and Hello should be considered equal). I can't GROUP BY lower(choice) because I want all columns in the result-set. Grouping by all columns causes all records to return, including all duplicates.
1. Closest I've gotten
select lower(choice), count(choice) as votes from answers where question_id = 21 group by lower(choice) order by votes desc;
The issue with this is it will not return all columns.
lower | votes
-----------------------------------------------+-------
dancing in the moonlight | 8
pumped up kicks | 7
party rock anthem | 6
sexy and i know it | 5
moves like jagger | 4
2. Trying with all columns
select *, count(choice) as votes from answers where question_id = 21 group by lower(choice) order by votes desc;
Because I am not specifying every column from the SELECT in my GROUP BY, this throws an error telling me to do so.
3. Specifying all columns in the GROUP BY
select *, count(choice) as votes from answers where question_id = 21 group by lower(choice), id, user_id, question_id, choice order by votes desc;
This simply dumps the table with votes column as 1 for all records.
How can I get the vote count and unique representative records from 1., but with all columns from the table returned?
Join grouped results back with primary table, then show only one row for each (question,answer) combination.
similar to this:
WITH top5 AS (
select question_id, lower(choice) as choice, count(*) as votes
from answers
where question_id = 21
group by question_id , lower(choice)
order by count(*) desc
limit 5
)
SELECT DISTINCT ON(question_id,choice) *
FROM top5
JOIN answers USING(question_id,lower(choice))
ORDER BY question_id, lower(choice), answers.id;
Here's what I ended up with:
SELECT answers.*, cc.votes as votes FROM answers join (
select max(id) as id, count(id) as votes
from answers
group by trim(lower(choice))
) cc
on answers.id = cc.id ORDER BY votes desc, lower(response) asc

t-sql how to select records without a duplicated one column

I want to select rows for all employess without repeating the data in one column.
For example I have two rows where salary (before raise) is displayed, how can I display only the largest figure without duplication.
You can use Row_Number function
Here is a sample code
select * from (
select *,
row_number() over (partition by empid, name, department order by salary desc) as rn
from employee
) employee where rn = 1
You can find Row_Number() with Partition By clause sample at http://www.kodyaz.com
If I'm understanding the question correctly, then a simple MAX function and GROUP BY would work.
SELECT EmployeeId, OtherColumns, MAX(Salary)
FROM tblEmployees
GROUP BY EmployeeId, OtherColumns