Postgres array_agg each value at new string within one row - sql

I have such a query
SELECT group_id, array_agg(element_id) FROM table
GROUP BY group_id;
As a result I have something like that:
group_id | array_agg
106 | {2147,2138,2144}
107 | {2132,2510,2139}
What query should be written, so result may be depicted in this way:
group_id | array_agg
106 | {2147
| 2138
| 2144}
107 | {2132
| 2510
| 2139}

Basically one should format the output in a client app, however you can use string_agg() with a new-line character:
select group_id, string_agg(element_id::text, e'\n')
from my_table
group by group_id;
group_id | string_agg
----------+------------
106 | 2147 +
| 2138 +
| 2144
107 | 2132 +
| 2510 +
| 2139
(2 rows)

Related

Add running number in select statement based on a column

I have a view receipt_data that includes contract_no and receipt_no columns - something like this:
contract_no | receipt_no | Amount
------------+------------+---------
1176 | ABMN1024 | 100
1176 | ABMN1027 | 767
1176 | ABMN1027 | 345
NULL | MNDF7132 | 389
NULL | NULL | 673
1046 | MDGF2344 | 454
I need to query this view with running number added to it. Running number should be added as following.
run_no |contract_no | receipt_no | Amount
----------+------------+------------+--------
1 | 1176 | ABMN1024 | 100
2 | 1176 | ABMN1027 | 767
| 1176 | ABMN1027 | 345
3 | NULL | MNDF7132 | 389
| NULL | NULL | 673
4 |1046 | MDGF2344 | 454
The running number must be like
Add running number to unique contract_no + receipt_no
If receipt_no has value then return running number
If receipt_no is null, there's no need to add running number, skip it
Is it possible to script like this? Please help
you can try by using row_number() analytic function
select
case when receipt_no is not null
then
row_number()over(order by (select null))
else null end as run_no,t.* from
table_name t

For a given table give out the count for each row Oracle SQL

if i have a table like this:
ID | Name | Payment
----------------------
101 | Victor | 10
103 | Andy | 13
134 | Mai | 2
156 | Chris | 68
179 | Ryan | 43
And I wanna have a query that gives out the following
[Count] | ID | Name | Payment
----------------------
1 | 101 | Victor | 10
2 | 103 | Andy | 13
3 | 134 | Mai | 2
4 | 156 | Chris | 68
5 | 179 | Ryan | 43
So it gives out the number of each row but I don't know how to do it ( am a beginner at SQL). Any tips?
Simply use row_number():
select row_number() over (order by id) as "Count",
t.*
from t
order by "Count";
You should have both order bys to be sure the numbering on the rows is correct and the order of the rows in the result set is correct.
use dense_rank()
select *,dense_rank() over(order by id) from t
or you could use count()
select *,count(*) over(order by id) from t
simple
select rownum, ID , Name, Payment from table

Comparing sets of values in same table

I'm trying to compare two sets of data in the same table to verify an update operation. I've created this query to view the different sets of information side-by-side, but when I add an additional constraint in the WHERE clause, I get zero rows returned.
The following query shows me the two record sets next to each other, so I can kinda eyeball that there are different componentids:
WITH src AS
(SELECT id AS s_id,
moduleid AS s_moduleid,
instanceid AS s_instanceid,
tagid AS s_tagid,
componentid AS s_componentid
FROM component_junction WHERE id=103)
SELECT * FROM component_junction cj
JOIN src ON s_moduleid=cj.moduleid
AND s_instanceid=cj.instanceid
AND s_tagid=cj.tagid
WHERE cj.id=117
Returns:
id | moduleid | instanceid | tagid | componentid | s_id | s_moduleid | s_instanceid | s_tagid | s_componentid
----|----------|------------|-------|-------------|------|------------|--------------|---------|--------------
117 | 2923 | 7179 | 1 | <null> | 103 | 2923 | 7179 | 1 | <null>
117 | 2923 | 7179 | 2 | <null> | 103 | 2923 | 7179 | 2 | <null>
117 | 2924 | 1404 | 1 | <null> | 103 | 2924 | 1404 | 1 | <null>
117 | 2924 | 1404 | 2 | <null> | 103 | 2924 | 1404 | 2 | <null>
117 | 1 | 41 | 2 | <null> | 103 | 1 | 41 | 2 | 267
117 | 1 | 40 | 2 | <null> | 103 | 1 | 40 | 2 | 267
117 | 1 | 38 | 2 | <null> | 103 | 1 | 38 | 2 | 267
But the below query does not return me any rows. Note the extra AND clause at the end:
WITH src AS
(SELECT id AS s_id,
moduleid AS s_moduleid,
instanceid AS s_instanceid,
tagid AS s_tagid,
componentid AS s_componentid
FROM component_junction WHERE id=103)
SELECT * FROM component_junction cj
JOIN src ON s_moduleid=cj.moduleid
AND s_instanceid=cj.instanceid
AND s_tagid=cj.tagid
WHERE cj.id=117 AND s_componentid != cj.componentid;
I know the values are different since I can see it in the result set from the first query. Some NULL values are present in both sets for componentid so I'd expect those not to show in the second query.
One or both values appear to be NULL. Postgres supports the ANSI standard NULL safe comparison, so change
s_componentid != cj.componentid
to:
s_componentid is distinct from cj.componentid
As one NULL value differs from another NULL value, you may use ISNULL function for ComponentID column like below:
WITH src AS
(SELECT id AS s_id,
moduleid AS s_moduleid,
instanceid AS s_instanceid,
tagid AS s_tagid,
ISNULL(componentid,'') AS s_componentid
FROM component_junction WHERE id=103)
SELECT * FROM component_junction cj
JOIN src ON s_moduleid=cj.moduleid
AND s_instanceid=cj.instanceid
AND s_tagid=cj.tagid
WHERE cj.id=117
AND ISNULL(s_componentid,'') != ISNULL(cj.componentid,'');

How to write sql LEAD() and LAG() query in interbase?

This query gives the desired results when working with Oracle as my back-end.
select field1,
field2
from
(select field1,
field2,
LEAD(field2) over (order by r) name
from
(select rownum r,
field1,
field2
from t3
where field2 = 1
)
)
where v != nvl(name, -1);
But I am facing issues while querying to Interbase database because analytical functions lag() and lead()are not supported in InterBase6.
My requirement is, if array field2={1,3,4,4,3,4}, then I should get results as {1,3,4,3,4}.
I have no idea on interbase but I can give you points to write a query to replicate lead function. You can build on that.
Find a column you want to order the rows by. The rownum you are using in your oracle query is not a correct way to do so. As you cannot guarantee that the results will be displayed in same order all the time. So assuming field1 is the column you want to order by.
Now find a way to generate a sequence number from 1 - n in interbase, based on the order above. where n being your total number of rows. So your sample table might look like below.
+-----+--------+--------+
| seq | field1 | field2 |
+-----+--------+--------+
| 1 | 101 | 1 |
| 2 | 102 | 3 |
| 3 | 103 | 4 |
| 4 | 104 | 4 |
| 5 | 105 | 3 |
+-----+--------+--------+
Once you have achieved the above task, you are almost done. You just have to do a self join to replicate lead or lag function. Here is example of lead
select t1.field1
,t1.field2
,t2.field1 as lead_field1
,t2.field2 as lead_field2
from table1 t1
left join
(select seq-1 as prev_seq,field1,field2
from table1) t2
on t1.seq=t2.prev_seq
The output of this query will be like this, which is what you need to replicate lead function.
+--------+--------+-------------+-------------+
| field1 | field2 | lead_field1 | lead_field2 |
+--------+--------+-------------+-------------+
| 101 | 1 | 102 | 3 |
| 102 | 3 | 103 | 4 |
| 103 | 4 | 104 | 4 |
| 104 | 4 | 105 | 3 |
| 105 | 3 | NULL | NULL |
+--------+--------+-------------+-------------+
Sample for the same could be found at
http://rextester.com/IJIU40428

Getting the top 5 call durations for each phone extention in MS Access

|--------------------------------------------------------------|
| ID. EXT phneNumber duration |
|--------------------------------------------------------------|
| 78172 101 2233379092 00:00:23.0 |
| 78175 104 2233818185 00:08:15.0 |
| 78176 101 9339444840 00:04:56.0 |
| 78177 108 2581594433 00:01:28.0 |
| 78179 104 2533815944 00:02:30.0 |
| 78180 101 2335343977 00:00:00.0 |
| 78181 101 2335343977 00:01:36.0 |
| 78186 108 9229661175 00:00:53.0 |
| 78193 104 2538633408 00:00:00.0 |
| 78194 108 2580013364 00:00:11.0 |
| 78196 104 2583300164 00:00:16.0 |
| 78197 104 9963341189 00:02:44.0 |
| 78198 101 9663319313 00:03:58.0 |
| 78199 101 2104834340 00:03:19.0 |
| 78205 104 2222020401 00:00:00.0 |
|--------------------------------------------------------------|
The table above shows a part of the data in a microsoft Access 2007 database.
EXT is the extension of a phone
phneNumber is the number that was called from that extention
duration is the amount of time that the called lasted
I need to write a query to find the 5 Longest(in duration) calls per extention. The desired result is showed below
|--------------------------------------------------------------|
| ID. EXT phneNumber duration |
|--------------------------------------------------------------|
| 78176 101 9339444840 00:04:56.0 |
| 78198 101 9663319313 00:03:58.0 |
| 78199 101 2104834340 00:03:19.0 |
| 78181 101 2335343977 00:01:36.0 |
| 78172 101 2233379092 00:00:23.0 |
| 78175 104 2233818185 00:08:15.0 |
| 78197 104 9963341189 00:02:44.0 |
| 78179 104 2533815944 00:02:30.0 |
| 78196 104 2583300164 00:00:16.0 |
| 78193 104 2538633408 00:00:00.0 |
| 78177 108 2581594433 00:01:28.0 |
| 78186 108 9229661175 00:00:53.0 |
| 78194 108 2580013364 00:00:11.0 |
|--------------------------------------------------------------|
I tried the below query but is not working as desired and it's very slow as well.
SELECT *
FROM (SELECT DISTINCT ext, phneNumber, duration FROM transactions) t
WHERE t.duration IN ( SELECT TOP 5 duration
FROM transactions
WHERE t.ext = ext
ORDER BY duration desc);
First, I don't see why you are using distinct in the outer from clause. See if this does what you want:
SELECT ext, phneNumber, duration
FROM transactions as t
WHERE t.duration IN ( SELECT TOP 5 t2.duration
FROM transactions t2
WHERE t.ext = t2.ext
ORDER BY t2.duration desc);
TOP in MS Access works differently from top in SQL Server and Sybase, because it returns duplicates. That is, it can return more than five rows if there are duplicates.
If that is an issue, you might try:
SELECT ext, phneNumber, duration
FROM transactions as t
WHERE t.id IN (SELECT TOP 5 t2.id
FROM transactions t2
WHERE t.ext = t2.ext
ORDER BY t2.duration desc, t2.id
);