sql query sort but display specific values on top - sql

For example I have a table with names as column1 and date as column2. I want to query where specific names will be on top, and dates will be sorted in descending order.
|names|dates|
|a |2016 |
|b |2013 |
|c |2017 |
|d |2011 |
I want to display a table where b and c will be on top, but dates columns will be sorted in desc order and the rest of the names will be displayed as the dates columns is sorted. its like having two groups where values b and c has their dates sorted and the rest by another sorted dates. for example
|names|dates|
|b |2017 |
|c |2013 |
|a |2016 |
|d |2011 |
What sql query should I use?

If you want all b and c on top sorted by dates then rest, try this:
ORDER BY (CASE WHEN names = 'b' or names = 'c' THEN '1' else '2' END) ASC, dates desc
DEMO
http://sqlfiddle.com/#!9/8c6ba6/1
If you want all b on top, then all c then rest, try this:
ORDER BY (CASE WHEN names = 'b' THEN '1'
WHEN names = 'c' THEN '2' else '3' END) ASC, dates desc
DEMO
http://sqlfiddle.com/#!9/8c6ba6/2

Related

Looking for Postgres query which can provide output like MongoDB group by function

Product table
|_id|name |
|---|------|
|3 |Laptop|
Size table
|_id|product_id|size|
|---|----------|----|
|5 |3 |15 |
|6 |3 |17 |
Query:
select tp._id, tp.name, ts.size from test_product tp
left join test_size ts on tp._id = ts.product_id
group by tp._id, tp.name, ts.size
where tp._id = 3 limit 10 offset 0
Current output:
|_id|name |size|
|---|------|----|
|3 |Laptop|15 |
|3 |Laptop|17 |
Expected output
|_id|name |size |
|---|------|-------|
|3 |Laptop|[15,17]|
Note:
Due to current query I'm getting 2 record for the same product and my limit and offset query logic is getting false and not getting proper count. I'm not well aware of Postgres queries for this kind of situation. So I need solution for this so my limit and offset logic will be correct for fetching data and for this query my count of product will be 1.
Use array_agg():
SELECT
tp._id,
tp.name,
ARRAY_AGG(ts.size ORDER BY ts.size) -- ORDER BY to get consistent results
FROM
test_product tp
LEFT JOIN test_size ts ON tp._id = ts.product_id
GROUP BY
tp._id,
tp.name
WHERE
tp._id = 3
LIMIT 10
OFFSET 0;
The ORDER BY within the aggregation is optional, but it's always nice to get consistent results over and over again.

Select rows that are duplicates on two columns

I have data in a table. There are 3 columns (ID, Interval, ContactInfo). This table lists all phone contacts. I'm attempting to get a count of phone numbers that called twice on the same day and have no idea how to go about this. I can get duplicate entries for the same number but it does not match on date. The code I have so far is below.
SELECT ContactInfo, COUNT(Interval) AS NumCalls
FROM AllCalls
GROUP BY ContactInfo
HAVING COUNT(AllCalls.ContactInfo) > 1
I'd like to have it return the date, the number of calls on that date if more than 1, and the phone number.
Sample data:
|ID |Interval |ContactInfo|
|--------|------------|-----------|
|1 |3/1/2017 |8009999999 |
|2 |3/1/2017 |8009999999 |
|3 |3/2/2017 |8001234567 |
|4 |3/2/2017 |8009999999 |
|5 |3/3/2017 |8007771111 |
|6 |3/3/2017 |8007771111 |
|--------|------------|-----------|
Expected result:
|Interval |ContactInfo|NumCalls|
|------------|-----------|--------|
|3/1/2017 |8009999999 |2 |
|3/3/2017 |8007771111 |2 |
|------------|-----------|--------|
Just as juergen d suggested, you should try to add Interval in your GROUP BY. Like so:
SELECT AC.ContactInfo
, AC.Interval
, COUNT(*) AS qnty
FROM AllCalls AS AC
GROUP BY AC.ContactInfo
, AC.Interval
HAVING COUNT(*) > 1
The code should like this :
select Interval , ContactInfo, count(ID) AS NumCalls from AllCalls group by Interval, ContactInfo having count(ID)>1;

Count and max aggregate function in same table in one query

I have to do count and max aggregate function in same query. For example I have history table contains date column. I need to retrieve the latest date as well as count () with some criteria. Criteria is applicable for only count() . I am able to retrieve the latest date using max and rank function.But could not merge both. Could you please assist?
Update:
Scenario : Customer buys/sells Shares.
Input: Table Share_history and Table Customer and Table Share and Table Share_Status
Customer :
Cust_id |Cust_name
1 |A
2 |B
Share :
Share_id|Share_Name|Owner|
10 |ABC |XYZ |
20 |BCD |MNC |
Share_Status :
Share_Status_Id|Share_Status_Name
1 |Buy
2 |Sell
Share_history :
Share_history _id|Share_id|Trans_date|Share_status_Id|Cust_id
100 |10 |12/12/14 | 1 |1
101 |10 |24/12/14 | 2 |1
102 |10 |14/01/15 | 1 |1
103 |10 |28/02/15 | 2 |1
103 |10 |16/03/15 | 1 |1
Output: latest Trans_date and count(no of times specific share was bought(1)) and Cust_id=1.
Query:
select share1.Share_id,SHAREHIST.Latest_Date,SHAREHIST.buycount
from Share share1 left outer join
(select share_id,max(Trans_date) keep(dense_rank last order by share_id) as Latest_Date,
(select count(*) as buycount from Share_history where Share_status_id=1 and Share_id=share1.Share_id)
from Share_history
group by Share_id
) SHAREHIST
on SHAREHIST.share_id=share1.share_id
EXPECTED :
Share_id|Latest_Date|buycount
10 |16/03/15 | 3
Try using this:
SELECT
Share_id
,Trans_Date
,COUNT(Share_id) buycount
FROM
(
SELECT
*
FROM Share_history SH
WHERE Trans_Date = (SELECT MAX(Trans_Date) FROM Share_history)
) SH
GROUP BY Share_id, Trans_Date
Rest of the joins I think you can add.
I think you just want aggregation:
select sh.share_id, max(trans_date) as trans_date, count(*) as buy_count,
from share_history sh
where cust_id = 1
group by sh.share_id;

Fetch data from multiple tables in postgresql

I am working on an application where I want to fetch the records from multiple tables which are connected through foreign key. The query I am using is
select ue.institute, ue.marks, uf.relation, uf.name
from user_education ue, user_family uf where ue.user_id=12 and uf.user_id=12
The result of the query is
You can see the data is repeating in it. I only want a record one time. I want no repetition. I want something like this
T1 T2
id|name|fid id|descrip| fid
1 |A |1 1|DA | 1
2 |B |1 2|DB | 1
2 |B |1
Result which I want:
Result:
id|name|fid|id|descrip| fid
1 |A |1 |1|DA | 1
2 |B |1 |2|DB | 1
2 |B |1 |
The results fetched through your query
The total rows are 5
More Information
I want the rows of same user_id from both tables but you can see in T1 there are 3 rows and in T2 there are 2 rows. I do not want repetitions but also I want to fetch all the data on the basis of user_id
Table Schemas,s
T1
T2
I can't see why you would want that, but the solution could be to use the window function row_number():
SELECT ue.institute, ue.marks, uf.relation, uf.name
FROM (SELECT institute, marks, row_number() OVER ()
FROM user_education
WHERE user_id=12) ue
FULL OUTER JOIN
(SELECT relation, name, row_number() OVER ()
FROM user_family
WHERE user_id=12) uf
USING (row_number);
The result would be pretty meaningless though, as there is no ordering defined in the individual result sets.

How to select records with order id in SQLite

I have a query that selects data in an alphabetical order. For example:
ID |TITLE
6 |A
35 |AA
3 |B
87 |BB
...
And I would like to select an order id of the record as well (order id it's not an actual column in the db). So the result should look like:
ID |ORDER ID |TITLE
6 |0 |A
35 |1 |AA
3 |2 |B
87 |3 |BB
...
How can I achieve something like this? I could check every returned record in a while loop and I would increase a counter on every iteration but that's not really what I want to do and I would rather leave this on database.
This is kind RANK function in other database engines.
In SQLite, you can achieve this like:
SELECT ID, (SELECT COUNT() FROM table AS t WHERE Title<table.Title), Title FROM table;
dense_rank and sqlite - possible?
EDIT: Distinct order numbers:
SELECT ID, (SELECT COUNT() FROM table AS t WHERE Title<table.Title OR Title=table.Title AND ROWID<table.ROWID), Title FROM table;
Something like this:
SELECT * FROM yourtable WHERE id = 3 ORDER BY title
This will return all fields in yourtable (id, order id, title) where the id column is 3
Edited to add:
Additional information from comment - include order_id in result set but not from table. To to this you can add a constant and alias the column like so:
SELECT id, '999' AS order_id, title FROM yourtable WHERE id = 3 ORDER BY title
This will return an order_id column with 999 as the value.