MS Access SQL Query with grouping across rows and columns - ms-access

I have a table in MS Access with following layout. I am using MS Access 2019
Category1 Qty1 Category2 Qyt2
================================
A 10 B 2
B 3 C 4
A 2 A 4
C 3 B 3
I want the output as
Category Qty
================
A 16
B 8
C 7
Please suggest how to achieve this using query in MS Access.
Thanks

Use UNIONALL and GROUP BY in inner sub query
HERE CHECK SQL Fiddle
SELECT Category, SUM(Qty) as Qty FROM (
SELECT Category1 AS Category, Qty1 AS Qty FROM TAB1
UNION ALL
SELECT Category2 as Category, Qty2 AS Qty FROM TAB2
) as TAB
GROUP BY TAB.Category

Rearrange data with UNION query into normalized structure should be in first place.
SELECT Category1 AS Cat, Qty1 AS Qty, 1 AS Src FROM tablename
UNION SELECT Category2, Qty2, 2 FROM tablename;
Use that query as source for an aggregate query.

Related

Better way to use UNION

i have a table products that have 5 fields to supplier
code supplier_1 supplier_2 supplier_3
000001 3 87 25
000002 12 5 48
I have to bring the code of product and all suppliers that have relation with
For that i create a query of each supplier and relate then
like
select code supplier1
from products
union
select code supplier2
from products
... and so on
there is another way to do that ?
Starting in MySQL 8.0.14, you can use a lateral join:
select t.code, s.supplier
from t cross join lateral
(select supplier_1 as supplier union all
select supplier_2 as supplier union all
select supplier_3 as supplier union all
select supplier_4 as supplier
) s;

Count Category products with mysql

I have to count products inside each category like I have a category A that have two childs B and C.
In B category have 10 products and C category have 5 Products.
I want to write a query that count product like A = 15 B = 10 C = 5.
I have wrote a query that count only for child categories.
My query is given below
SELECT
c.`id`,
c.`parent_id`,
c.`name`,
c.`slug`,
c.`route_id`,
c.`description`,
c.`excerpt`,
c.`sequence`,
c.`image`,
c.`seo_title`,
c.`meta`,
c.`enabled`,
(SELECT
COUNT(`product_id`)
FROM
HM_category_products
WHERE
HM_category_products.category_id IN (SELECT
HM_categories.`id`
FROM
HM_categories
WHERE
(id = c.`id` OR id = c.`parent_id`))) AS count
FROM
`HM_categories` AS c
EDITED :- Below is my tables structure. This is just an example.
Category Table
id parent_id name slug enabled
1 0 Mobiles & Tablets mobiles-tablets 1
2 1 Mobile Phones mobile-phones 1
3 1 Tablets tablets 1
4 1 Mobile Accessories mobile-accessories 1
5 0 Electronics & Computers electronics-computers 1
6 5 Cameras & Accessories cameras-accessories 1
7 5 TV - Video - Audio tv-video-audio 1
Category Product Table
product_id category_id
1 2
2 2
3 2
4 2
5 3
6 2
7 3
8 3
9 3
10 2
11 3
12 2
13 2
14 2
15 2
You hav to use the "Group by" with something like:
SELECT
category_id, COUNT(*)
FROM
HM_category_products
GROUP BY category_id
This would get your table HM_category_products Grouped by category_id so will know how mane rows of each category its in the table, whats mean you will know the number of product of each category. Then you can join this resulting table with category one to get the category info. (Sorry for my english)
The GROUP BY statement is used in conjunction with the aggregate
functions to group the result-set by one or more columns. SQL GROUP BY Statement
for more info abaut "Group by" read
12.16.2 GROUP BY Modifiers and
12.16.1 GROUP BY (Aggregate) Functions
EDIT: I see now what you whant. I already give you the direction but here its a step furder: DISCLAIMER: THIS QUERY ITS JUST EXAMPLE, IT DOSNT WORK
CREATE VIEW view_2 AS
SELECT
category_id, COUNT(*) AS product_sum
FROM
HM_category_products
GROUP BY category_id
CREATE VIEW view_1 AS
SELECT
*
FROM
HM_categories
LEFT JOIN
view_2 AS a ON HM_categories.id = a.category_id;
SELECT
id,
name,
(SELECT
SUM(product_sum)
FROM
view_1
WHERE
parent_id = final.id) as product_count
FROM
HM_categories AS final;
that way you will get the product of a parent category, your only missing a CASE on the last select "product_count" to the child categorys, but that sum its easy because you already hav it on the view_1 (again sorry for my english)

SQL Table Solution With Calculating Different Columns in Same Table

I have a sql table like :
id buy_product buy_product_total sell_product sell_product_total
1 apple 5
2 banana 8
3 cake 20
4 apple 1
5 cake 2
6 apple 2
My problem is, I want to show product name and how many product left. Like :
product_name left
apple 6
cake 18
How can I show like that solution with sql query ?
I create table as answerers as :
Buy Table
id product_name total
1 apple 5
2 banana 8
3 cake 20
4 apple 2
Sell Table
id product_name total
1 apple 1
2 cake 2
I want to table like this
product_name left
apple 6
banana 8
cake 18
Is not a good table, could be better that buy and sell to be the same collumn buy with positive values and sell with negative.
But answer your question, suppose that your table name is myTable,
obs: you can execute every select separeted to understand better
select buy_product as product_name, (buy_total - sell_total) as left
from (
(select buy_product, sum(buy_product_total) as buy_total
from myTable where buy_product_total is not null group by buy_product) as buy_list
inner join
(select sell_product, sum(sell_product_total) as sell_total
from myTable where sell_product_total is not null group by sell_product) as sell_list
on buy_list.buy_product = sell_list.sell_product
)
As others have noted, your table structure is less than optimal.
However, given what you have, this will give you the results you're after.
select product, sum(total) from
(
select buy_product as product, buy_product_total as total
from yourtable
where buy_product is not null
union
select sell_product, -sell_product_total
from yourtable
where sell_product is not null
) v
group by product
Or, with your two tables
select product_name, sum(total) from
(
select product_name, total
from buy_table
union
select product_name, -total
from sell_table
) v
group by product_name
You should consider a different database design that is more appropriate (You may want to read up on normalization), but query follows:
SELECT t1.buy_product_total - t2.sell_product_total
FROM ProductTable t1, ProductTable t2
WHERE t1.buy_product = t2.sell_product
i.e. You're joining the table to itself using a 'self join'...

need help to shorten mysql multiple OR conditions

I have a table which contains manager id and staff ids (comma separated) and i have the following sql statement:
SELECT manager_id, staff_ids
FROM manager_staffs
WHERE 1 IN (staff_ids)
OR 3 IN (staff_ids)
OR 5 IN (staff_ids)
OR 23 IN (staff_ids)
OR 12 IN (staff_ids)
OR 16 IN (staff_ids)
OR 19 IN (staff_ids)
OR 32 IN (staff_ids)
OR 123 IN (staff_ids)
............
basically, it is a very long query with a lot of 'OR' condition. I would like to improve or shorten it if there is a way.
need help from all the sql gurus.
The problem is your data structure - don't put all the staff ids in one column. Make a table - you can call it manager_staff:
CREATE TABLE manager_staff (
manager_id int,
staff_id int
);
And so you can make records that show which manager every staff person reports to. Then your query becomes:
select manager_id, staff_id from manager_staff where staff_id in (1,3,...);
Im not sure what are you trying to achieve but try this:
SELECT manager_id, staff_ids
FROM manager_staffs
WHERE staff_ids in ('1','3' and so on)
Assuming staff_ids is a comma separated field then you could do the following.
SELECT DISTINCT manager_id, staff_ids
FROM manager_staffs a
INNER JOIN (SELECT 1 AS staff_id UNION SELECT 3 UNION SELECT 5 UNION SELECT 23 UNION SELECT 12 UNION SELECT 16 UNION SELECT 19 UNION SELECT 32 UNION SELECT 123) b
ON FIND_IN_SET(b.staff_id, a.staff_ids) > 0
But as I commented earlier, splitting it up would be a far better idea
why dont you try this
SELECT manager_id, staff_ids
FROM manager_staffs
WHERE staff_ids IN (1,3,5,23,12,16,19,32,123,.......)
you have no choice how to reduce your ORs only if you create other table and select them like query above.
structure your table is best to get performance when retrieving data.
your table should look like that
manager_staff
manager_id , staff_id
1 1
1 3
1 5
1 23
..........

MySql Result Set Combine Columns

I have this result set from my query:
OrderId CustomerId ProducerId CustomerPayment ProducerPayment
1 1 3 10 5
1 1 4 10 5
1 2 3 10 5
1 2 4 10 5
I need to return this result into this:
OrderId UserId Payment
1 1 20
1 2 20
1 3 10
1 4 10
Just combining the CustomerId and ProducerId into UserId. Same with the Payment Columns.
Is there any way to achieve this with using just a simple select and group by? I'm avoiding temp tables, calling multiple same queries and like for optimization. I hope this is possible.
Thanks a lot
SELECT
OrderId,
CustomerID AS UserId,
SUM (CustomerPayment) As Payment
FROM orders
UNION ALL
SELECT
OrderId,
ProducerId AS UserId,
SUM (ProducerPayment) As Payment
FROM orders
Try something like this:
select
OrderId,
CustomerId,
sum(CustomerPayment) Payment,
group_concat(OrderId separator ',') listOrders /* list all OrderID's from the user and separates these with a , */
from your_table
group by CustomerId
Dont know how you query looks like atm?