sqlite3: group by x having count(y > N) - sqlite

I have a table users with this structure:
id | user | offset
0 | alvin | -1
1 | alvin | -2
2 | alvin | 5
3 | alvin | 6
4 | simon | -5
5 | simon | -4
6 | theodore | -1
7 | theodore | 1
I want a query that returns the distinct usernames which have at least 1 positive entry AND at least 1 negative entry in offset. In this example, the query would return "alvin" and "theodore" but not "simon".
I've looked at a number of other posts related to GROUP BY, HAVING, COUNT(), and combinations thereof, but none of them seem to address this idea of counting the number of true returns from a conditional statement. In particular, I think I'm misunderstanding how to incorporate aggregate functions like count() into the WHERE clause (or if that's even possible). When I try something like:
SELECT user FROM users WHERE count(offset > 0) > 0;
I get an error: misuse of aggregate function count()
(I know that statement doesn't full specify the query I want - it's meant more as an indication of how I've been trying to approach the problem.)
I'm coming from a Python/Pandas mindset here, and it may just be that this approach doesn't translate well to SQL.
Any advice much appreciated!

This could be done with a compound query:
SELECT user
FROM users
WHERE offset > 0
UNION
SELECT user
FROM users
WHERE offset < 0;
It is actually possible to use aggregation functions.
However, COUNT() counts rows; to count something else, it is a better idea to use a boolean expression (returning 0 or 1), and SUM() that:
SELECT user
FROM users
GROUP BY user
HAVING SUM(offset < 0) > 0
AND SUM(offset > 0) > 0;

Related

Sqlite subtract different rows from different columns

Let's say that I have sql table like this:
id | val_1 | val_2
1 | 55 | 300
2 | 90 | 600
3 | 80 | 200
..
Now, I wan't to subtract 300-90, and next 600-80 and so on with offset of one row. Table can be odd count like this. Is there a chance to do this without loop and external functions? I use Python api for sqlite3.
Thanks in advance!
Depending on the output that you want you can use LEAD() window function:
SELECT *,
val_2 - LEAD(val_1, 1, 0) OVER (ORDER BY id) AS difference
FROM tablename;
or LAG() window function:
SELECT *,
LAG(val_2, 1, 0) OVER (ORDER BY id) - val_1 AS difference
FROM tablename;
See the demo.

Interactive Grid:Process with PL/SQL only that isn't based off a table

Env: Oracle APEX v5.1 with Oracle 12c Release 2
Firstly, I have created an Interactive Grid that isn't based off an underlying table as I will process this manually using PL/SQL.
I have been using the following as a guide:
https://apex.oracle.com/pls/apex/germancommunities/apexcommunity/tipp/6361/index-en.html
I basically have the following query:
select
level as id,
level as grid_row,
null as product,
null as product_item
from dual connect by level <= 1
Concentrating on just the product and product_item columns where the product_item column will be a readonly column and only the product number can be entered, I would like to achieve the following:
Product Product Item
---------- -------------
123456 123456-1
123456 123456-2
556677 556677-1
654321 654321-1
654321 654321-2
654321 654321-3
123456 123456-3
From the above, as the user types in the Product and then tabs out of the field, I would like a DA to fire that will add the sequence of "-1" to the end of that product number. Then is the user then adds another row within the IG and enters the same product number, I then want it to append "-2" to the end of it.
Only when the product changes number, I need the sequence to reset to "-1" for that new product as per 556677 and so forth.
Other scenarios that should also be taken into consideration are as follows:
From above IG, the user entered 123456 again but this should calculate that the next sequence for 123456 is "-3"
The same needs to be catered for, when a Product is removed from the IG but to always look at the max sequence number for that product.
I was thinking of possibly using APEX_COLLECTIONS as a means of storing what is currently in the grid, since no changes have been committed to the database.
Assuming you have a collection of product values (in this case, I am using the built-in SYS.ODCINUMBERLIST which is a VARRAY data type) then the SQL for your output would be:
SELECT id,
id AS grid_row,
product,
product || '-' || ROW_NUMBER() OVER ( PARTITION BY product ORDER BY id )
AS product_item
FROM (
SELECT ROWNUM AS id,
COLUMN_VALUE AS product
FROM TABLE(
SYS.ODCINUMBERLIST(
123456,
123456,
556677,
654321,
654321,
654321,
123456
)
)
)
ORDER BY id
Output:
ID | GRID_ROW | PRODUCT | PRODUCT_ITEM
-: | -------: | ------: | :-----------
1 | 1 | 123456 | 123456-1
2 | 2 | 123456 | 123456-2
3 | 3 | 556677 | 556677-1
4 | 4 | 654321 | 654321-1
5 | 5 | 654321 | 654321-2
6 | 6 | 654321 | 654321-3
7 | 7 | 123456 | 123456-3
db<>fiddle here
As you mentioned, the data you enter is not saved into the DB whilst you are inserting your products, so it is not in fact stored anywhere.
So you cannot go check if that value already exists and enter a -2 or other.
Some things to consider would be to maybe save the values into a temp table so you can then have a function go check how many product_item like 123456-% are in there and use that number +1 as your new product_item.
Or you could go the even harder way and do it all with javascript. For this you will need to somehow get all records in the IG, go through them all and see how many occurences of 123456 you have and then insert 123456-(no of occurences + 1).

T-SQL Server ORDER BY date and nulls last

I am studying for exam 70-761 and there is a challenge asking to place nulls in the end when using order by, I know the result is this one:
select
orderid,
shippeddate
from Sales.Orders
where custid = 20
order by case when shippeddate is null then 1 else 0 end, shippeddate
what i don't know is why the 1 and 0 and how they affect the result can anyone clarify.
Best Regards,
Daniel
There are two parameters in your order clause, it like to split two groups and then continue sort items inside those groups
First, because 0 less than 1, so all the orders without shippeddate will be push to last.
Then we will order by shippeddate
Example:
orderID | shippeddate
| null
| today
| null
| yesterday
| tomorrow
First sort by case when shippeddate is null then 1 else 0 end we will got
orderID | shippeddate
| today
| yesterday
| tomorrow
| null
| null
then continue sort with shippeddate, we will got
| yesterday
| today
| tomorrow
| null
| null
hope it useful to you

Getting output of duplicates and not the same as another column

Example database:
column1 | column2
--------+---------
1 | 1
2 | 1
3 | 3
4 | 3
5 | 5
6 | 7
7 | 3
I would like to get an output of
2 | 1
4 | 3
7 | 3
This is the query I use:
SELECT
column2, COUNT(*) c
FROM
table
GROUP BY
column2
HAVING
c > 1
which returns:
1 | 2
3 | 3
I would like to take it a step further:
SELECT *
FROM table
WHERE (column1 != column2 AND having count(*) > 1)
The first SQL
SELECT column2, COUNT(*) c
FROM table
GROUP BY column2
HAVING c > 1
returns a nice list of the column2 values you want. You will need a self-JOIN and get the column1's that go with. That will require using table aliases. You could try it this way
SELECT T1.column1, T1.column2
from table T1
JOIN (SELECT column2, count(*) c
FROM table
GROUP BY column2
HAVING c > 1) T2 ON T2.column2 = T1.column2
WHERE T1.column1 <> T2.column2
[Author's note] This is not the answer as originally written. The stack help re: editing says:
Edits are expected to be substantial and to leave the post better than
you found it. Common reasons for edits include:
To fix grammar and spelling mistakes
To clarify the meaning of the post (without changing that meaning)
To include additional information only found in comments, so all of the information relevant to the post is contained in one place
To correct minor mistakes or add updates as the post ages
To add related resources or hyperlinks
The edit does not meet any of the criteria. However, on the same page it says:
If you are not comfortable with the idea of your contributions being
collaboratively edited by other trusted users, this may not be the
site for you.
So be it.

peculiar teradata clause, Column_Name >= ''

I have a statament wrote for teradata by someone who don't work here anymore, so i can't ask him directly.
In this statament, the last clause in the where is : ... and Column_Name >= '' .I have no clue about what should that clause do.
If it matter Column_name is a [decimal](7,0) NULL.
Can someone explain to me which case are accepted and which are refused by that clause ?
to me it seams that should allow trough everything since everything is major or equal to null
When you compare a string to a numeric value the string is converted to a FLOAT, in your case the empty string '' is treated as 0, so this is just a stupid way to check for Column_Name >= 0 and filters negative values and NULL. You never know if this was actually the intention of the guy who wrote it :)
When >='' clause is applied on a character column then it will restrict the null records.
If the table has 2 columns one Region_cd & rank_nr and the data in the table is as below:-
select * from databasename.tablename;
*** Query completed. 5 rows found. Two column returned.
*** Total elapsed time was 1 second.
Region | rank_nr
---------- -----------
emea | 1
amr | 2
apac | 3
? | 4
| 5
? is represents NULL and space in region_cd column for rank=5 is not visible
If we query in this table with where clause as Region>='' then it will result below 4 rows:-
select * from databasename.tablename where Region_cd >='' ;
*** Query completed. 4 rows found. 2 columns returned.
*** Total elapsed time was 1 second.
col1 | rank_nr
---------- -----------
emea | 1
apac | 3
amr | 2
| 5

Resources