Counting checked items in database - vb.net

In my database I have table with multiple "yes/no" rows on which I would like to run some selection check if they are selected or not.
ITEM ORDERED ORDER_ID
item1 true 1
item2 false 1
item3 true 2
item4 true 3
item5 true 4
item6 true 4
In datagridview in my code I will like to achieve this.
ORDER STATUS
1 not ordered
2 ordered
3 ordered
4 ordered
In my code I will like to go through all orders and check if status of ordered items on that order is true. If all items on some order have status true, then i will like to set another flag that I have in ORDER table to true(ordered). Which is the most elegant way to solve this problem? If you have some example of this like problem I will really appreciate it. Thanks in advance.

It appears STATUS means whether all rows for that ORDER_ID have ORDERED = True. If that is correct, I think you can get what you need with an Access aggregate (GROUP BY) query.
True is stored as -1 and False is stored as 0. So if the maximum ORDERED value for any ORDER_ID is 0, you know there is at least one item for that order which has not yet been ordered. If the maximum is -1, then all items have been ordered.
Start with a query to determine Max(ORDERED) for each ORDER_ID.
SELECT y.ORDER_ID, Max(y.ORDERED) AS MaxOfORDERED
FROM YourTable AS y
GROUP BY y.ORDER_ID;
Once you have that working, use it as a subquery in another with an IIf expression to transform MaxOfORDERED to the STATUS text you want.
SELECT
sub.ORDER_ID,
IIf(sub.MaxOfORDERED = 0, 'not ordered', 'ordered') AS STATUS
FROM
(
SELECT y.ORDER_ID, Max(y.ORDERED) AS MaxOfORDERED
FROM YourTable21030926a AS y
GROUP BY y.ORDER_ID
) AS sub
ORDER BY sub.ORDER_ID;

Related

Counting how many times one specific value changed to another specific value in order of date range and grouped by ID

I have a table like below where I need to query a count of how many times each ID went from specifically 'Waste Sale' in one value to 'On Stop' in the very next value based on ascending date and if there are no instances of this, the count will be 0
ID
Stage name
Stage Changed Date
1
Waste Sale
06-05-2022
1
On Stop
08-06-2022
1
Cancelled
09-02-2022
2
Waste Sale
06-05-2022
2
On Stop
07-05-2022
2
Waste Sale
08-06-2022
2
On Stop
10-07-2022
3
Cancelled
10-07-2022
3
On Stop
11-07-2022
The result I would be looking for based on the above table would be something like this:
ID
Count of 'Waste Sales to On Stops'
1
1
2
2
3
0
ID 1 having a count of 1 because there was one instance of 'Waste Sale' changing to 'On Stop' in the very next value based on date range
ID 3 having a count of 0 because even though the stage name changed to 'On Stop' the previous value based on date range wasn't 'Waste Sale'.
I have a hunch I would have to use something like LEAD() and GROUP BY/ ORDER BY but since I'm so new to SQL would really appreciate some help on the specific syntax and coding. Any version of SQL is okay.
We can use window function lead to take a peek at the next value of the query result.
select distinct id,
(
select count(*)
from
(
select *,
lead(stage_name)
over(
partition by id
order by stage_changed_date)
as stage_next
from sales s2
) s3
where s3.id = s1.id
and s3.stage_name = 'waste sale'
and s3.stage_next = 'on stop'
) as count_of_waste_sales_to_on_stop
from sales s1
order by id;
Query above uses lead(stage_name) over(partition by id order by stage_changed_date) to get the next stage_name in the query result while segregating it by id and order it based on stage_changed_date. Check the query on DB Fiddle.
Note:
I have no experience in zoho, so i'm unsure if the query will 100% works or not. They said it supported ansi-sql, however there might some differences with MySQL due to reasons.
The column names are not the exact same with op question due to testing only done using DB Fiddle.
There might better query out there waiting to be written.

How to summarize table based on other column values?

There is a decision table as follows:
Id decision
1 NULL
1 NULL
1 yes
1 NULL
2 no
2 no
2 no
3 yes
3 no
3 yes
The result should return :
Id decision
1 Decision Pending
2 no
3 yes
So for each Id in the decision table:
If any of the decision value is NULL then it is to be set to
"decision pending". eg. id 1
If there is no NULL and any of the decision is yes then final
decision is set to be "yes". eg. id 3
If there is no NULL and all the decisions are no then final decision
is set to be as "no". eg. id 2
What should the azure sql query to get the above mentioned result?
P.S. I am new to SQL, so having trouble figuring this out.
SELECT
id,
CASE
WHEN COUNT(*) > COUNT(decision)
THEN 'pending'
ELSE MAX(decision)
END
AS decision
FROM
decision
GROUP BY
id
GROUP BY id ensures that you get one row per id.
COUNT(*) tells you how many rows there are for that id.
COUNT(decision) tell you how many of those rows have NOT NULL decisions.
COUNT(*) > COUNT(decision) is therfore TRUE if any of the decisions in the group are NULL.
MAX(decision) returns yes if there are any yes values in the group, and no only if there aren't any yes values in the group.
One way is to compare the count(*) and count(decision) which reveals if a row is null and use an inline if to succinctly know to use the aggregate
select id, Iif(Count(*)=Count(decision),Max(decision),'Decision Pending')
from Decision
group by id

google bigQuery subqueries to joins

I have the following table. basically simplified version of my table. I need to aggregate few columns, I will explain what I am trying to do and also what I have written till now.
tableName
food.id STRING NULLABLE
food.basket.id STRING NULLABLE
food.foodType STRING NULLABLE
food.price INTEGER NULLABLE
food.printed BOOLEAN NULLABLE
food.variations RECORD REPEATED
food.variations.id INTEGER REPEATED
food.variations.amount INTEGER NULLABLE
Sample data
id basket.id. foodType. price. printed. variations.id variations.amount
1. abbcd. JUNK. 100. TRUE. NULL. NULL
2. cdefg. PIZZA. 200. TRUE. 1234. 10
2345. 20
5678. 20
3. abbcd. JUNK. 200. FALSE. 1234. 10
4. uiwka. TOAST. 500. FALSE. NULL. NULL
variations can be like pizza toppings, each variation has an amount, say veggie toppings cost 10 cent and meat toppings cost 20 cents for simplicity
so now I am trying to aggregate some data for this table
I am trying to get
number of items printed (items where printed = TRUE)
number of items unprinted (items where printed = FALSE)
total cost of all items
total price of all variations
total number of unique baskets for a specific foodType
This is the query I have:
select SUM(CASE When item.printed = TRUE Then 1 Else 0 End ) as printed,
SUM(CASE When item.printed = FALSE Then 1 Else 0 End) as nonPrinted,
SUM(item.price) as price,
(select COUNT(DISTINCT(item.basket.id)) from tableName where itemType = "JUNK") AS baskets,
(select SUM(CASE when m.amount is NULL then 0 Else m.amount END) as variations_total from tableName, UNNEST(item.variations) as m) as variations
from tableName;
printed. unprinted. price. baskets. variations.
2. 2. 1000. 1. 60
Now I get the result that I expect. I am trying to understand if we can do this without using subqueries and use only joins?
Below is for BigQuery Standard SQL and assumes that your query is really working (saying this because your data example does not exactly fit into query you provided)
So, below two subqueries
(select COUNT(DISTINCT(item.basket.id)) from tableName where itemType = "JUNK") AS baskets,
(select SUM(CASE when m.amount is NULL then 0 Else m.amount END) as variations_total from tableName, UNNEST(item.variations) as m) as variations
can be replace with
COUNT(DISTINCT IF(itemType = "JUNK", item.basket.id, NULL)) AS baskets,
SUM((SELECT SUM(amount) FROM item.variations)) AS variations
Believe me or not - but result will be the same
Row printed nonPrinted price baskets variations
1 2 2 1000 1 60
So, as you can see yo don't need subqueries and you don't need joins here either
Note: in the second row - (SELECT SUM(amount) FROM item.variations) is not really the same type of subquery as in your original query. Rather here for each row you query its array to find sum of amount in that row which is then being aggregated to total sum ...
Hope you get it

Modifying column value according to status, and adding extra rows. (sql)

In my table I have a "name" column and a "status" column.
the status is either true or false.
And another table contains a number which is a total amount.
The result that I want to get is a table with two columns:
name | status
and and example of a data:
a | available
a | available
a | not available
a | not available
a | available
when "a" is in the name column and the availability is the status column.
The total amount from the second table indicates the total number of "a" rows that i need to have, and the status depends on the true/false from the status column in the original table.
If the status is "true" I need to write "available" and when "false" then "not available".
If the total amount value is bigger than the data I have in the first table, I need to add rows according to the total amount with the status "available".
For example, If I have 3 records of "a", when one has the status "true" and the other two have the status "false", and the total amount is 4, In the result I need to get 4 rows with the name "a", 2 of them "available" and 2 "not available" (the given 3 rows, plus one row to make it 4).
My question is, how can I change the value according to the data in the table? (Write available/ not available)
And how can I add a certain amount of rows with preset values (same name as before, and "available" status)?
"...how can I change the value according to the data in the table?"
You can use CASE() to test for the value of the column.
SELECT name,
CASE WHEN status = 'true'
THEN 'available'
ELSE 'not available'
END status
FROM tableName
For future answer-seekers:
To get the 'fake' rows, one way is to use are recursive CTE:
WITH Expanded_Data as (SELECT Counted_Data.name,
CAST('true' as VARCHAR(5)) as status,
Counted_Data.count + 1 as count,
Total.count as limit
FROM (SELECT name, COUNT(*) as count
FROM Data
GROUP BY name) Counted_Data
JOIN Total
ON Counted_Data.name = Total.name
AND Counted_Data.count < Total.count
UNION ALL
SELECT name, status, count + 1, limit
FROM Expanded_Data
WHERE count < limit)
SELECT name, CASE WHEN status = 'true'
THEN 'available'
ELSE 'not available' END
FROM (SELECT name, status
FROM Data
UNION ALL
SELECT name, status
FROM Expanded_Data) d;
(have a working SQL Fiddle example.)
I'm a little worried about the initial duplication in the source data though; I can only hope there is more 'unique' information as well.

SQL, WHERE id=5, but i want a certain record to show up first.

not sure how to do this but say i have a table with a bunch of items owned by userID 5, I want to make it so that if i search for a specific item from that user, all of his items will show up, but the item searched for will appear first and the rest of the items will follow. For example:
Items table
-----------
itemID userID itemName
1 5 Coffee Mug
2 5 iPhone
3 5 LCD Monitor
4 5 Macbook pro
5 5 Shell
So say i do a search for an iPhone, i want my results to return all of userID's items (WHERE userID=5), but... I want the iPhone item to be at the top of the list! Thanks all for your help!
damien
EDIT now we are no longer searching for 'iPhone' we are indicating first item by #ItemID:
ORDER BY
CASE WHEN itemID = #ItemID THEN 'a' ELSE 'z' END
--, secondary ordering
ORDER BY
case when Items.itemID = 2 then 0 else 1 end ASC
,Items.itemName ASC
Create an additional column for the SELECT with a case statement that is 0 when your condition is satisfied and 1 otherwise, and then ORDER BY that.