SQL-Retrieve only the Total count of occurences of a specific column [duplicate] - sql

Think I have a table with two fields: ID and State. State value (that is boolean) can be 0 or 1. ID isn't unique so the table looks like this:
ID | State |
-----------------
1 | true |
-----------------
1 | false |
-----------------
2 | false |
-----------------
3 | true |
-----------------
1 | true |
Now, I want to count every rows group by ID field and have State as two different columns in resultset. So it should look like this:
ID | TrueState | FalseState |
------------------------------------
1 | 2 | 1 |
------------------------------------
2 | 0 | 1 |
------------------------------------
3 | 1 | 0 |
How to do that?

This is a pivot query, which mysql doesn't support. The workarounds get ugly fast, but since you're only going to be generating two new columns, it won't be horribly ugly, just mildly unpleasant:
SELECT SUM(State = True) AS TrueState, SUM(State = False) AS FalseState,
SUM(State is NULL) AS FileNotFoundState
...
Basically state = true will evaluate to boolean true/false, which MySQL will type-cast to an integer 0 or 1, which can them be SUM()med up.

Related

Postgresql Use ID from another column as base

I got table with 2 IDs. I'm using parametrs as filters.
eg.
| ID | DIFF_ID |
| ----| ------ |
| 1 | null |
| 2 | 3 |
| 3 | null |
...
As you can see Diff_ID has the same int as ID and I need to use DIFF_ID to show other values in table by using parametrs eg.
case when $P{aba} is true then DIFF_ID (...) = ID(?) end
if the paramter 'aba' is true then use DIFF ID as base but show up as ID.
I'm expecting DIFF_ID appear in ID column if the parameter is true.

Setting value of boolean columns based on existence of value in set

I have a SQL table of the format (INTEGER, json_array(INTEGER)).
I need to return results from the table that have two boolean columns. One is set to true iff a 1 appears in the json_array, and the other true iff a two appears in the array. Obviously there is not mutual exclusion.
For example, if the data were this:
-------------------------------
| ID | VALUES |
-------------------------------
| 12 | [1, 4, 6, 11] |
_______________________________
| 74 | [0, 1, 2, 5] |
-------------------------------
I would hope to get back:
-------------------------------
| ID | HAS1 | HAS2 |
-------------------------------
| 12 | true | false |
_______________________________
| 74 | true | true |
-------------------------------
I have managed to extract the json data out of the values column using json_each, but am unsure how to proceed.
If I recall correctly, SQLite max aggregate function supports boolean, therefore you can simply group by your data:
select
t1.id,
max(case json_each.value when 1 then true else false end) as has1,
max(case json_each.value when 2 then true else false end) as has2
from
yourtable t1,
json_each(t1.values)
group by
t1.id

Update the first and last records only amongst many duplicate records

I have a table in Access named Spells which holds patient spells (where a patient has a spell within a hospital). It's structure is as below:
| ID | SpellID | MultipleSpell | FirstSpell | LastSpell |
|----|---------|---------------|------------|-----------|
| 1 | 1 | False | | |
| 2 | 2 | True | | |
| 3 | 2 | True | | |
| 4 | 3 | False | | |
| 5 | 4 | False | | |
| 6 | 5 | True | | |
| 7 | 5 | True | | |
| 8 | 5 | True | | |
The MultipleSpell column indicates that there are multiple occurrences of the spell within the table.
I'd like to run query which would update the FirstSpell column to True for records with the IDs of 1,2,4,5,6. So basically, where a Spell is the first one in the table, it should be marked, in the FirstSpell column.
I would also then like to update the LastSpell column to True for records with the IDs of 1,3,4,5,8.
The reasoning for this (if you're interested) is that the table links to a separate table containing the name of wards. It would be useful to link to this other table and indicate whether the ward is the admitting ward (FirstSpell) or the discharging ward (LastSpell)
You can update the first using:
update spells
set firstspell = 1
where id = (select min(id)
from spells as s2
where spells.spellid = s2.spellid
);
Similar logic (using max()) can be used for the last spell.

Access SQL Select rows that have value in common with results of condition

Let's say I have a simple table, with the following format:
==================================
| ID | Invoice | Box | Delivered |
==================================
| 1 | AA11 | 1 | True |
----------------------------------
| 2 | AA11 | 2 | False |
----------------------------------
| 3 | AA22 | 1 | False |
----------------------------------
| 4 | AA33 | 1 | False |
----------------------------------
| 5 | AA44 | 1 | True |
----------------------------------
ID is a unique integer, Invoice is a TEXT field, Box is an Integer, and Delivered being a boolean (or BIT, as it's know in Access).
A query like this gets a list of everything that has been delivered:
SELECT * FROM Deliveries WHERE Delivered = True
However, each invoice can have multiple boxes (as is the case with invoice 1111), and sometimes not all the boxes are delivered at the same time. If a box has been delivered, I would like to be able to get the status of the other boxes with the same invoice number.
I know I can run multiple queries to do this. The one I mentioned above, and then another which loops through all the return results, and then runs another select with Invoice = ####.
Is there a way to do this all in a single query? I think it might be WHERE EXISTS, but I can't find out how to structure the query.
Ideally, I want the rows returned for a single query of the above able to be rows with ID's: 1, 2, and 5. This is the output I am looking for:
==================================
| ID | Invoice | Box | Delivered |
==================================
| 1 | 1111 | 1 | True |
----------------------------------
| 2 | 1111 | 2 | False |
----------------------------------
| 5 | 4444 | 1 | True |
----------------------------------
So that even though Delivered = False for ID 2, it is still returned because another item with the same invoice number has Delivered = True
When trying out some queries I got the error
Cannot join on memo, ole or hyperlink Object
Assuming you want something like this
select * from invoice where invoice in (SELECT invoice FROM invoice WHERE Delivered = 'True')
With the nested query your selecting an outputting the invoice numbers for reference in the parent query. Here the output of the nested query is used to 'filter' the results.
You already got it to work, but here is the another way, without changing the table.
SELECT invoice.ID, invoice.Invoice, invoice.Box, invoice.Delivered, invoice_1.Delivered AS Expr1
FROM invoice, invoice AS invoice_1
WHERE (((invoice.Invoice)=[invoice_1].[Invoice]) AND (([invoice_1].[Delivered])=Yes));
You can test it here.
For those getting into the same problem there is an explanation and a solution here
Apologies if I messed up the Access syntax:
select id
from T
group by id
having sum(iif(Delivered, 1, 0) < count(*)
Call the above query IC (incomplete). You may want to see all the undelivered data along with the ids:
select * from T
where id in (<IC>) and Delivered = false

Is there a single query that can update a "sequence number" across multiple groups?

Given a table like below, is there a single-query way to update the table from this:
| id | type_id | created_at | sequence |
|----|---------|------------|----------|
| 1 | 1 | 2010-04-26 | NULL |
| 2 | 1 | 2010-04-27 | NULL |
| 3 | 2 | 2010-04-28 | NULL |
| 4 | 3 | 2010-04-28 | NULL |
To this (note that created_at is used for ordering, and sequence is "grouped" by type_id):
| id | type_id | created_at | sequence |
|----|---------|------------|----------|
| 1 | 1 | 2010-04-26 | 1 |
| 2 | 1 | 2010-04-27 | 2 |
| 3 | 2 | 2010-04-28 | 1 |
| 4 | 3 | 2010-04-28 | 1 |
I've seen some code before that used an # variable like the following, that I thought might work:
SET #seq = 0;
UPDATE `log` SET `sequence` = #seq := #seq + 1
ORDER BY `created_at`;
But that obviously doesn't reset the sequence to 1 for each type_id.
If there's no single-query way to do this, what's the most efficient way?
Data in this table may be deleted, so I'm planning to run a stored procedure after the user is done editing to re-sequence the table.
You can use another variable storing the previous type_id (#type_id). The query is ordered by type_id, so whenever there is a change in type_id, sequence has to be reset to 1 again.
Set #seq = 0;
Set #type_id = -1;
Update `log`
Set `sequence` = If(#type_id=(#type_id:=`type_id`), (#seq:=#seq+1), (#seq:=1))
Order By `type_id`, `created_at`;
I don't know MySQL very well, but you could use a sub query though it may be very slow.
UPDATE 'log' set 'sequence' = (
select count(*) from 'log' as log2
where log2.type_id = log.type_id and
log2.created_at < log.created_at) + 1
You'll get duplicate sequences, though, if two type_ids have the same created_at date.