Getting COUNT while ignoring GROUP BY - mysql

I have the following table: ProductSales
+-------+-----------+--------+-----------+
|prod_id|customer_id|order_id|supplier_id|
+-------+-----------+--------+-----------+
| 1 | 1 | 1 | 1 |
+-------+-----------+--------+-----------+
| 2 | 4 | 2 | 2 |
+-------+-----------+--------+-----------+
| 3 | 1 | 1 | 1 |
+-------+-----------+--------+-----------+
| 4 | NULL | NULL | Null |
+-------+-----------+--------+-----------+
| 5 | 1 | 1 | 2 |
+-------+-----------+--------+-----------+
| 6 | 4 | 7 | 1 |
+-------+-----------+--------+-----------+
| 7 | 1 | 1 | 3 |
+-------+-----------+--------+-----------+
I have a SELECT query:
SELECT customer_id AS customer, count(*) AS prod_count
, count(DISTINCT order_id) as orders
FROM ProductSales
WHERE supplier_id=1
GROUP BY customer_id
HAVING customer_id<>'NULL'
This will be produce the result:
+--------+----------+------+
|customer|prod_count|orders|
+--------+----------+------+
| 1 | 2 | 1 |
+--------+----------+------+
| 4 | 1 | 1 |
+--------+----------+------+
What I have been trying to achieve and getting nowhere is to add a fourth column in my results to show the number of order_ids that belong only to the current supplier for each customer:
+--------+----------+------+-------------+
|customer|prod_count|orders|Unique Orders|
+--------+----------+------+-------------+
| 1 | 2 | 1 | 0 | } Order '1' is connected with two supplier_ids
+--------+----------+------+-------------+
| 4 | 1 | 1 | 1 | } Order '2' is connected to only one supplier_id
+--------+----------+------+-------------+
(This gets more complex when there are more orders per customer associated with far more suppliers).
I thought I was close with:
SELECT t1.user_id, count(DISTINCT t1.prod_id) AS prod_count
, count(DISTINCT t1.order_id) as orders
, IF(count(DISTINCT t3.supplier_id)>1,0,1) AS Unique_Orders
FROM ProductSales AS t1
LEFT JOIN `order` AS t2 ON t1.order_id=t2.order_id
LEFT JOIN ProductSales AS t3 ON t2.order_id=t3.order_id
WHERE t1.supplier_id=1
GROUP BY t1.customer_id
HAVING t1.customer_id<>'NULL'
The orders table stated above is related to ProductSales only by order_id.
Which shows my Customers, Products(total), Orders(total) but the Unique Orders shows if there are unique orders (0) or not (1), I understand the logic of the IF statement and it does what I expect. It's working out how to find the number of unique orders which is baffling me.
The table is established and can't be changed.
Any suggestions?

Unique orders can be defined as
SELECT OrderID
FROM yourtable
GROUP BY OrderID
Having COUNT(Distinct SupplierID) = 1
So try
SELECT
customer_id AS customer,
count(*) AS prod_count.
count(DISTINCT productsales.order_id) as orders,
COUNT(distinct uqo)
FROM ProductSales
left join
(
SELECT Order_ID uqo
FROM Productsales
GROUP BY Order_ID
Having COUNT(Distinct supplier_id) = 1
) uniqueorders
on ProductSales.order_id = uniqueorders.uqo
WHERE supplier_id=1
GROUP BY customer_id

Related

How to get calculated data from one column in database

im new in sql. I cannot get data with format what i want in one step. Now i'm using more sql commands. I want to get all data in one command because i cant to connect them in subquery with group by. Somebodys can help me?
example of Table i have:
id
order_id
order_status
1
1
0
2
1
0
3
1
0
4
1
1
5
1
1
6
2
0
7
2
0
8
2
1
Table i want to have after sql query:
order_id
count
of
progress(%)
1
2
5
40
2
1
3
33
queries i use:
SELECT order_id, COUNT(status) as count
FROM `orders`
WHERE status = 1
GROUP by order_id;
SELECT order_id, COUNT(status) as of
FROM `orders`
GROUP by order_id;
SELECT order_id,
CAST((SELECT COUNT(status) FROM `orders` WHERE status = 1) /
(SELECT COUNT(status) FROM `orders`) *100 as int) AS progress FROM orders
group by order_id;
but last working properly only if i use where to single order id.
I want to make this data in one sql query to format i showed up.
Thanks a lot guys!
You don't need subqueries to do this, SQL's ordinary aggregate functions already work as you want with your group by clause:
SELECT order_id,
SUM(order_status) AS `count`,
COUNT(*) AS `of`,
SUM(order_status) / COUNT(order_status) * 100 as `progress`
FROM orders
group by order_id;
See example at http://sqlfiddle.com/#!9/d1799db/4/0
you need to use multiple subqueries
here's a query that I used and worked on your example on the onecompiler.com website
-- create
CREATE TABLE EMPLOYEE (
order_id INTEGER,
order_status INTEGER
);
-- insert
INSERT INTO EMPLOYEE VALUES (1,0 );
INSERT INTO EMPLOYEE VALUES (1, 0);
INSERT INTO EMPLOYEE VALUES (1, 0);
INSERT INTO EMPLOYEE VALUES (1, 1);
INSERT INTO EMPLOYEE VALUES (1,1 );
INSERT INTO EMPLOYEE VALUES (2, 0);
INSERT INTO EMPLOYEE VALUES (2, 0);
INSERT INTO EMPLOYEE VALUES (2, 1);
select *
from EMPLOYEE;
SELECT order_id, count, off , count/off
from(
select distinct order_id as order_id,
(select count(order_id) from EMPLOYEE C WHERE A.order_id=C.order_id AND order_status =1) as 'count',
(select count(order_id) from EMPLOYEE B WHERE A.order_id=B.order_id ) as 'off'
FROM EMPLOYEE A
) AA
;
You need to use sum and count with group by.
create table orders(
id int,
order_id int,
order_status int);
insert into orders values
(1,1,0),
(2,1,0),
(3,1,0),
(4,1,1),
(5,1,1),
(6,2,0),
(7,2,0),
(8,2,1);
select
order_id,
sum(order_status) count,
count(order_id) "of",
(100 * sum(order_status))
/ count(order_id) progress
from orders
group by order_id
order by order_id;
order_id | count | of | progress
-------: | ----: | -: | -------:
1 | 2 | 5 | 40.0000
2 | 1 | 3 | 33.3333
db<>fiddle here
i was described my problem without some details, w i want to join with other table but i see only record with status
oders_details
| id | order_describe | order_date |
|:----:|:--------------:|:----------:|
| 1 | sample 1 | 2022-02-28 |
| 2 | sample 2 | 2022-02-28 |
| 3 | sample 3 | 2022-03-01 |
| 4 | sample 4 | 2022-03-02 |
orders_status
| id | order_id |order_status|
|:---:|:---------------:|:----------:|
| 1 | 1 | 0 |
| 2 | 1 | 0 |
| 3 | 1 | 0 |
| 4 | 1 | 1 |
| 5 | 1 | 1 |
| 6 | 2 | 0 |
| 7 | 2 | 0 |
| 8 | 2 | 1 |
table i want after query
orders_view
| id |order_id|order_describe| order_date | count | of | progress |
|-----|--------|--------------|------------|-------|----|:--------:|
| 1 | 1 | sample 1 | 2022-02-28| 2 | 5 | 40 |
| 2 | 2 | sample 2 | 2022-02-28| 1 | 3 | 33 |
| 3 | 3 | sample 3 | 2022-03-01| null |null| null |
| 4 | 4 | sample 4 | 2022-03-02| null |null| null |
i want to get some hint what i have todo, to get finally table or view, not complete solution, to better understand sql lang

How to calculate max values of groups?

I have a table like so (I'm not sure how to format tables)
Category / Products / Purchases
1 | A | 12
1 | B | 13
1 | C | 11
2 | A | 1
2 | B | 2
2 | C | 3
Expected output:
1 | B | 13
2 | C | 3
However I keep on getting
1 | A | 13
2 | A | 3
ie. It just selects the first occurrence of the second column.
Here is my code:
SELECT Category, Products, MAX(Purchases) FROM myTable GROUP BY Category;
Use filtering in the where clause:
select t.*
from t
where t.purchases = (select max(t2.purchases) from t t2 where t2.category = t.category);
With NOT EXISTS:
select m.* from myTable m
where not exists (
select 1 from myTable
where category = m.category and purchases > m.purchases
)
See the demo.
Results:
| Category | Products | Purchases |
| -------- | -------- | --------- |
| 1 | B | 13 |
| 2 | C | 3 |
You can use row_number() to identify max purchase for each group or replace rownumber() to rank() if there are ties of max purchases for each group
Select Category, Products,
Purchases from (Select Category,
Products,
Purchases,
row_number() over (partition by
category, products order by
purchases desc) rn from table) t
where t.rn=1
)

Update field based on duplicate values

I'm trying to update the value of a column based on duplicates in my database, but I'm struggling to find the correct query.
Here's my db structure:
id | product_id | order_id | parent_id
--------------------------------------
1 1 1 SMITH1
2 1 2 SMITH1
3 2 3 BLOGGS1
4 2 4 BLOGGS1
I want to update the order_id to be the same, where we have duplicates of both product_id AND parent_id.
Currently I've found the duplicates like so:
SELECT
*,
COUNT(parent_id),
COUNT(product_id)
FROM
mytable
GROUP BY parent_id, product_id
HAVING COUNT(parent_id) > 1
AND COUNT(product_id) > 1
But I'm now struggling with the update/join to set the order_id values the same (can be minimum order_id value preferably).
Any help appreciated!
With a join of the table to the minimum value of order_id for each combination of product_id and parent_id:
update mytable t inner join (
select product_id, parent_id, min(order_id) order_id
from mytable
group by product_id, parent_id
having min(order_id) <> max(order_id)
) tt on tt.product_id = t.product_id and tt.parent_id = t.parent_id
set t.order_id = tt.order_id;
This code will prevent any unnecessary updates in case there is only one order_id for that product_id and parent_id.
See the demo.
Results:
| id | product_id | order_id | parent_id |
| --- | ---------- | -------- | --------- |
| 1 | 1 | 1 | SMITH1 |
| 2 | 1 | 1 | SMITH1 |
| 3 | 2 | 3 | BLOGGS1 |
| 4 | 2 | 3 | BLOGGS1 |

Count the number of orders

I have a table (Table1) with the columns order_item_id customer_id and order_id in which I want to count the number of orders per customer. Unfortunately an order with more than one article has the same order_id
|order_item_id|order_id|customer_id|
| 2 | 30 | 1 |
| 3 | 30 | 1 |
| 4 | 42 | 1 |
| 5 | 33 | 2 |
| 11 | 32 | 3 |
| 12 | 33 | 2 |
| 13 | 33 | 2 |
| 19 | 69 | 3 |
Expected Outcome:
|numberOfOrders|customer_id|
| 2 | 1 |
| 1 | 2 |
| 2 | 3 |
I tried this (and many more):
CREATE TABLE X AS
SELECT
customer_id,
COUNT(order_id) AS `numberOfOrders`
FROM Table1 T1
GROUP BY customer_id;
The problem is, that with this solution it counts every article not the number of orders: so the number of orders for customer 1 is 3 (not 2), for customer 2 is 3 (not 1)....
How can I solve this for a big database with Mysql query?
Try the following solution to SELECT your data as expected:
SELECT COUNT(DISTINCT order_id) AS numberOfOrders, customer_id
FROM table1
GROUP BY customer_id
Demo: http://sqlfiddle.com/#!9/ee8f62/1/0
An option could be to do GROUP twice. First GROUP for the number of items per order, wrapped by a second GROUP for the number of orders per customer:
/* second group */
SELECT customer_id
, count(*) AS number_of_orders
FROM (
/* first group */
SELECT order_id
, customer_id
, count(*) AS order_item_count
FROM Table1
GROUP BY order_id, customer_id
) a
GROUP BY customer_id

MySQL Joining Tables While Counting & Grouping

I want to join 2 tables:
source_table
----------------------------------
| source_id label |
|----------------------------------|
| 1 Contact Form |
| 2 E-Mail |
| 3 Inbound Call |
| 4 Referral |
----------------------------------
related_table
---------------------------------------
| id created_at source |
|---------------------------------------|
| 1 2013-12-26 2 |
| 2 2013-12-26 2 |
| 3 2013-12-26 4 |
| 4 2013-12-25 1 |
| 5 2013-12-18 2 |
| 6 2013-12-16 4 |
| 7 2013-11-30 2 |
---------------------------------------
So that it looks like this:
---------------------------------------
| created_at source amount |
|---------------------------------------|
| 2013-12-26 E-Mail 2 |
| 2013-12-26 Referral 1 |
| 2013-12-25 Contact Form 1 |
| 2013-12-18 E-Mail 1 |
| 2013-12-16 Referral 1 |
---------------------------------------
I want to count the occurrences of each source in related_table grouped by the source for each date in the range.
But I'm not sure how to write the query.
Here's what I have so far:
SELECT DISTINCT
source_table.source_id,
source_table.label AS source,
related_table.created_at,
COUNT(*) AS amount
FROM source_table
INNER JOIN related_table
ON related_table.source=source_table.source_id AND
related_table.created_at>='2013-12-01' AND
related_table.created_at<='2013-12-31'
GROUP BY `source`
ORDER BY `created_at` ASC
I'm not very good with SQL, so the above query might be far off from what I need to have. All I know is that it doesn't work as expected.
My implementation:
select created_at, s.label, amount
from
(
select count(r.Source) as amount, r.source, r.created_at
from related_table r
group by r.source, r.created_at) a inner join source_table s
on a.source = s.source_id
where created_at between '2013-12-01' and '2013-12-31'
order by amount desc, created_at desc
http://sqlfiddle.com/#!2/841bd/2
adjusted demo to your example...
SELECT
created_at
,label as source
,COUNT(*) AS amount
FROM source_table
INNER JOIN related_table
ON source_table.source_id = related_table.source
GROUP BY label, created_at
ORDER BY created_at DESC