I'm trying to take the following data ,which is stored as rows on a SQL server:
ID Count Takings
1 null 4413
1 null 6258
1 null 3809
1 613 null
1 6 null
1 875 null
1 349 null
1 116 null
2 null 6916
2 null 2209
2 null 5255
2 290 null
2 197 null
2 393 null
2 737 null
2 268 null
3 null 9272
3 null 2862
3 698 null
3 393 null
and flatten the result to one row with the columns aggregated as such
ID Count Takings
1 1959 14480
2 1885 1091
3 1091 12134
Any help would be much appreciated. This is on a SQL Azure. So 2012+ I guess
Many thanks for any help everyone
Wayne
This is a perfect job for group by query:
select
[ID],
sum([Count]) as [Count],
sum([Takings]) as [Takings]
from
Table1
group by ID
A group by combines data together based on each unique combination of the columns being grouped. So for each unique value of ID, we aggregate the sum of Count and Takings.
Result (DEMO):
| ID | COUNT | TAKINGS |
|----|-------|---------|
| 1 | 1959 | 14480 |
| 2 | 1885 | 14380 |
| 3 | 1091 | 12134 |
Related
I have a table in PostgreSQL with the below values,
empid hyderabad bangalore mumbai chennai
1 20 30 40 50
2 10 20 30 40
And my output should be like below
empid city nos
1 hyderabad 20
1 bangalore 30
1 mumbai 40
1 chennai 50
2 hyderabad 10
2 bangalore 20
2 mumbai 30
2 chennai 40
How can I do this unpivot in PostgreSQL?
You can use a lateral join:
select t.empid, x.city, x.nos
from the_table t
cross join lateral (
values
('hyderabad', t.hyderabad),
('bangalore', t.bangalore),
('mumbai', t.mumbai),
('chennai', t.chennai)
) as x(city, nos)
order by t.empid, x.city;
Or this one: simpler to read- and real plain SQL ...
WITH
input(empid,hyderabad,bangalore,mumbai,chennai) AS (
SELECT 1,20,30,40,50
UNION ALL SELECT 2,10,20,30,40
)
,
i(i) AS (
SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
)
SELECT
empid
, CASE i
WHEN 1 THEN 'hyderabad'
WHEN 2 THEN 'bangalore'
WHEN 3 THEN 'mumbai'
WHEN 4 THEN 'chennai'
ELSE 'unknown'
END AS city
, CASE i
WHEN 1 THEN hyderabad
WHEN 2 THEN bangalore
WHEN 3 THEN mumbai
WHEN 4 THEN chennai
ELSE NULL::INT
END AS city
FROM input CROSS JOIN i
ORDER BY empid,i;
-- out empid | city | city
-- out -------+-----------+------
-- out 1 | hyderabad | 20
-- out 1 | bangalore | 30
-- out 1 | mumbai | 40
-- out 1 | chennai | 50
-- out 2 | hyderabad | 10
-- out 2 | bangalore | 20
-- out 2 | mumbai | 30
-- out 2 | chennai | 40
Simplifying a table 'Summary' to 2 columns: CoID, Type
There can be multiple types per CoID:
-----------
CoID | Type
-----------
150 | 2
150 | 5
233 | 2
120 | 1
120 | 2
I want to get a count of CoIDs that have only 1 Type. In this case CoID 233 would be the only one I'd want selected.
Thanks!
Look at Having clause from here
SELECT COUNT(Type), COID
FROM Customers
GROUP BY COID
HAVING COUNT(TYPE) = 1;
Just use Group by with Having clause for filtering:
SELECT COID, COUNT(Type)
FROM SUMMARY
GROUP BY COID
HAVING COUNT(COID) = 1
OUTPUT:
COID | COUNT(Type)
=====|=================
233 | 1
Live DEMO
I have the issue writing a sql script on PostgreSQL 9.6.6 which orders steps in a process by using the steps' parent-child ID's, and this grouped/partitioned per process ID. I couldn't find this special case here, so I apologize if I missed it and would please you to provide me the link to the solution in the comments.
The case: I have a table which looks like this:
processID | stepID | parentID
1 1 NULL
1 3 5
1 2 4
1 4 3
1 5 1
2 1 NULL
2 3 5
2 2 4
2 4 3
2 5 1
Now I have to order the steps by starting with the step where parentID is NULL for each processID .
Note: I cannot simply order StepID or parentID as new steps I put within the whole process get a higher stepID then the last step in the process (continuous generating surrogate key).
I have to order the steps for every processID, that I will receive the following output:
processID | stepID | parentID
1 1 NULL
1 5 1
1 3 5
1 4 3
1 2 4
2 1 NULL
2 5 1
2 3 5
2 4 3
2 2 4
I tried to do this with the CTE function WITH RECURSIVE:
WITH RECURSIVE
starting (processID,stepID, parentID) AS
(
SELECT b.processID,b.stepID, b.parentID
FROM process b
WHERE b.parentID ISNULL
),
descendants (processID,stepID, parentID) AS
(
SELECT b.processID,b.stepID, b.stepparentID
FROM starting b
UNION ALL
SELECT b.processID,b.stepID, b.parentID
FROM process b
JOIN descendants AS c ON b.parentID = c.stepID
)
SELECT * FROM descendants
The result is not what I am searching for. As we have hundreds of processes, I receive a list where the first records are the different processIDs which have a NULL value as parentID.
I guess I have to recursive the whole script on the processID again, but have no idea how.
Thank you for your help!
You should calculate the level of each step:
with recursive starting as (
select processid, stepid, parentid, 0 as level
from process
where parentid is null
union all
select p.processid, p.stepid, p.parentid, level+ 1
from starting s
join process p on s.stepid = p.parentid and s.processid = p.processid
)
select *
from starting
order by processid, level
processid | stepid | parentid | level
-----------+--------+----------+-------
1 | 1 | | 0
1 | 5 | 1 | 1
1 | 3 | 5 | 2
1 | 4 | 3 | 3
1 | 2 | 4 | 4
2 | 1 | | 0
2 | 5 | 1 | 1
2 | 3 | 5 | 2
2 | 4 | 3 | 3
2 | 2 | 4 | 4
(10 rows)
Of course, you can skip the last column in the final select if you do not need it.
How can I simulate a XOR function in PostgreSQL? Or, at least, I think this is a XOR-kind-of situation.
Lets say the data is as follows:
id | col1 | col2 | col3
---+------+------+------
1 | 1 | | 4
2 | | 5 | 4
3 | | 8 |
4 | 12 | 5 | 4
5 | | | 4
6 | 1 | |
7 | | 12 |
And I want to return 1 column for those rows where only one of the columns is filled in. (ignore col3 for now..
Lets start with this example of 2 columns:
SELECT
id, COALESCE(col1, col2) AS col
FROM
my_table
WHERE
COALESCE(col1, col2) IS NOT NULL -- at least 1 is filled in
AND
(col1 IS NULL OR col2 IS NULL) -- at least 1 is empty
;
This works nicely an should result in:
id | col
---+----
1 | 1
3 | 8
6 | 1
7 | 12
But now, I would like to include col3 in a similar way. Like this:
id | col
---+----
1 | 1
3 | 8
5 | 4
6 | 1
7 | 12
How can this be done is a more generic way? Does Postgres support such a method?
I'm not able to find anything like it.
rows with exactly 1 column filled in:
select * from my_table where
(col1 is not null)::integer
+(col1 is not null)::integer
+(col1 is not null)::integer
=1
rows with 1 or 2
select * from my_table where
(col1 is not null)::integer
+(col1 is not null)::integer
+(col1 is not null)::integer
between 1 and 2
The "case" statement might be your friend here, the "min" aggregated function doesn't affect the result.
select id, min(coalesce(col1,col2,col3))
from my_table
group by 1
having sum(case when col1 is null then 0 else 1 end+
case when col2 is null then 0 else 1 end+
case when col3 is null then 0 else 1 end)=1
[Edit]
Well, i found a better answer without using aggregated functions, it's still based on the use of "case" but i think is more simple.
select id, coalesce(col1,col2,col3)
from my_table
where (case when col1 is null then 0 else 1 end+
case when col2 is null then 0 else 1 end+
case when col3 is null then 0 else 1 end)=1
How about
select coalesce(col1, col2, col3)
from my_table
where array_length(array_remove(array[col1, col2, col3], null), 1) = 1
I have a database with VARCHAR column url. I would like to fetch rows so that the ones that have any url value have priority over other rows, but are ordered by date row (descending), so ORDER BY 'url' DESC, 'date' DESC wouldn't work as it would order them alphabetically first. Basically, it would look something like this:
Table:
ID | Url | Date
1 | http://...| 1001
2 | | 1002
3 | | 1003
4 | http://...| 1005
5 | http://...| 1004
Sorted:
ID | Url | Date
4 | http://...| 1005
5 | http://...| 1004
1 | http://...| 1001
3 | | 1003
2 | | 1002
What would be the proper zend framework way (or at least SQL query) to do it?
With SQL, you could so something like...
It gets kind of ugly if you allow null values on the url field as well.
SELECT * , IF(LENGTH(url) = 0 OR url IS NULL, 1, 0) AS nourl
FROM url ORDER BY nourl ASC
This basically checks to see if the url length is greater than zero or is null. If they are, they are at the bottom of the sort.
You could use order by field('field_name', value) desc in the select statement.