Dividing counts (PHP + MYSQL) - php

We are trying to sort through people that have purchased items to filter out people that have averaged purchasing over a certain amount of items per year.
Person 1 has bought 1.6 items/year. We want to exclude everyone below a certain amount. How can we do this?
id | item | year
1 | 1 | 2002
1 | 1 | 2003
1 | 3 | 2004
1 | 2 | 2004
2 | 2 | 2004
2 | 2 | 2003
1 | 4 | 2004

We got it. We used the query below and did the math in PHP.
$query = "SELECT id, COUNT(DISTINCT year), COUNT(item) from purchases GROUP BY id"

Related

select distinct sumof from mysql query with having

table structure
=====================================================================
id |fee_amount|fee_paid|fee_type|fee_user|date | Fee_for
=====================================================================
1 | 2000 | 500 | REG | 105 | 01.02.2017 | FEB
-----------------------------------------------
2 | 2000 | 1000 | REG | 105 | 03.02.2017 | FEB
-----------------------------------------------
3 | 2000 | 500 | REG | 105 | 04.02.2017 | FEB
-----------------------------------------------
4 | 1000 | 500 | FEE | 105 | 10.03.2017 | MAR
-------------------------------------------------------------
5 | 1000 | 500 | FEE | 105 | 11.03.2017 | MAR
--------------------------------------------------------------
6 | 1000 | 1000 | FEE | 105 | 13.03.2017 | APR
From the above I am saving the fee paying details
one student is paid the amount as partially on the above values
using this I need to get the total fees and total paid fees and the balance need to pay
for this I used
SELECT SUM(fee_amount) as fee, SUM(fee_paid) as paid ,fee_type
FROM tbl_fee A WHERE fee_user='105'
group by fee_type
having SUM(fee_amount)!=(SUM(fee_paid)
But its getting
6000 | 2000 | REG
2000 | 1000 | FEE
I need to get
2000 | 2000 | REG
1000 | 1000 | FEE
Just use this query to get the result that you need
SELECT fee_amount as fee, SUM(fee_paid) as paid ,fee_type FROM tbl_fee A WHERE fee_user='105' group by fee_type
If you do not want to sum the fee_amount field, then simply do not sum it up, but either include it in the group by clause or use the any_value() function to make your query compliant with the sql standard:
SELECT fee_amount as fee, fee_type, SUM(fee_paid) as paid
FROM tbl_fee A
WHERE fee_user='105'
group by fee_type, fee_amount
Obviously, these solutions assume that fee_amount is the same within a fee_type for all users. If the fee_amount can be different within a fee type and a user, then you need to specify how to handle such situations.

Find the total sum of class fees based on the class students enrolled over specific years using mysql or php

I am calculating for the total payments that are made by each class and by the student in a class he or she has ever been enrolled in, depending on the Academic Year.
Now the Student Class Table below has two students, the student with Student ID=0001 has been enrolled in two classes in two different years Class ID = 1, Year=2013 and Class ID=2, Year=2014.
However the student with Student ID=0002 only enrolled in one class and he left the school. Another student was enrolled in class with
Class ID = 1 in Year=2014
Student Class Table
| Student ID | Class ID | Year |
| 0001 | 1 | 2013 |
| 0002 | 1 | 2013 |
| 0003 | 1 | 2014 |
| 0001 | 2 | 2014 |
Below is the amount assigned to each student for each class in a particular period.
Designated Fees
| Class ID | Amount | Year |
| 1 | 100 | 2013 |
| 1 | 120 | 2014 |
| 2 | 210 | 2014 |
Now, I want to find the total amount each 'Class' is suppose to pay in the current year (thus in 2014), with the summation of what each class was suppose to pay in the previous year ( in this case, the 2013 is the previous Year) and the Previous Year (in this case, the 2014 is the current Year).
Using the below query will give you the amount each Student is suppose to pay from the previous year and current year as far is he/she enrolled in there.
This query gives a good results without any problems
SELECT
a.`Student ID`,
a.`Class ID`,
b.`Amount`,
a.`Year
FROM
`Student Class Table` a
JOIN
`Designated Fees` b
ON
a.`Class ID`=b.`Class ID`
and
a.Year=b.Year
QUERY RESULTS
| Student ID | Class ID | Amount | Year |
| 0001 | 1 | 100 | 2013 |
| 0002 | 1 | 100 | 2013 |
| 0003 | 1 | 120 | 2014 |
| 0001 | 2 | 210 | 2014 |
I want find the total class fees for all the years based on the students enrolled, using the current year as the base year, in this case year 2014 is the current year.
For instance
| Class ID | Total Fees | Year |
| 1 | 120 | 2014 |
| 2 | 410 | 2014 |
The Total Fees for the class with Class ID=1 is 120 because only a student was enrolled in that class within the Year 2013 and 2014 and thier allocated fees for the year 2014 is 120, Also the Total Fees for the
class with Class ID=2 is 410 because two students were enrolled in class with Class ID = 1 in Year 2013 and they were expected to pay an amount of 200, and in the Year 2014 Class 2, only one student enrolled and was expected to pay an amount of 210.
Well, my thoughts on solving this has been complicated, however I added a group by to the query afforementioned, this is wrong that I know. I wanted an Idea as to how to resolve this using either mysql or php, I can't seem to find my way around it.
This will be possible if you have batch numbers for the class from the time, the class was registered. This students in such a class will bear the batch No till they complete the school.
For instance, students in class with Class ID= 1 in Year=2013 will bear the same batch No till they complete. You can choose to create another table and reference it in the Student Class Table depending on how you promote students through the classes over the years.
Student Class Table
| Student ID | Class ID | Year | BatchNo |
| 0001 | 1 | 2013 | 1 |
| 0002 | 1 | 2013 | 1 |
| 0003 | 1 | 2014 | 2 |
| 0001 | 2 | 2014 | 1 |
After Adding the Batch No, you can simply group by the batchNo and sum the amount:
SELECT
a.`Student ID`,
a.`Class ID`,
sum(b.`Amount`),
a.`Year
FROM
`Student Class Table` a
JOIN
`Designated Fees` b
ON
a.`Class ID`=b.`Class ID`
and
a.Year=b.Year
GROUP BY batchNo
This will be your Results
| Class ID | Total Fees | Year |
| 1 | 120 | 2014 |
| 2 | 410 | 2014 |
You can go by this idea and I think, it can work well.

Doctrine2: SUM on left join query

I'm trying to build a query with Doctrine, but i'm not sure if it can be done.
What i need is to get a result displaying the ID of a Requested Item and its SUM of Quantity already fulfilled.
I have four tables:
Request
RequestItems
Order
OrderItems
I can create a Request and assign one or more Items to this Request which are stored at RequestItems, then i need to create an Order to this Request, the Order must aim to fulfill the Requested Items, but it might be with a single Order or Multiple ones, therefore each Order contains one or many items which are stored at OrderItems.
The following is an example of tables:
Request
| ID | Date |
|----|------------|
| 1 | 2014-05-12 |
| 2 | 2014-05-13 |
RequestItems
| ID | RequestID | Name |Qtty |
|----|-----------|---------------------|-----|
| 1 | 1 | 60W Light Bulb | 5 |
| 2 | 1 | Bticino switch | 3 |
| 3 | 2 | 60W Light Bulb | 10 |
| 4 | 2 | 80W Light Bulb Warm | 15 |
Order
| ID | RequestId | Date | State |
|----|-----------|------------|-------|
| 1 | 1 | 2014-05-14 | 1 |
| 2 | 1 | 2014-05-15 | 1 |
| 3 | 2 | 2014-05-15 | 1 |
| 4 | 2 | 2014-05-16 | 1 |
| 5 | 2 | 2014-05-17 | 1 |
OrderItems
| ID | RequestItemsID | OrderID | Qtty |
|----|----------------|---------|------|
| 1 | 1 | 1 | 5 |
| 2 | 2 | 2 | 3 |
| 3 | 3 | 3 | 2 |
| 4 | 3 | 4 | 2 |
| 5 | 3 | 5 | 1 |
| 6 | 4 | 5 | 10 |
Here i have two Requests:
No. 1: Have two items requested (5 60W light bulbs, 3 Bticino switches)
No. 2: Have one item requested (10 60W light bulbs, 15 80W warm light bulbs)
For these requests i have created 5 Orders, two of them to fulfill first request and 3 to fulfill second request.
The first two Orders have addressed the first request and provided the requested items so first request should be completed.
The last three Orders are addressing the second Request and have provided already 5 of the 10 60W light bulbs and 10 of the 80W warm light bulbs.
What i need here is to get the ID and Quantity of the RequestItems and The SUM of Qtty on OrderItems grouped by the RequestItem ID and filtered by the Order State and Request ID
As a sample i need to get how many RequestedItems where requested and have already been ordered for the Request No. 2 where its Order State is 1
| RequestItemsID | QttyRequested | QttyOrdered (SUM) |
|----------------|---------------|-------------------|
| 3 | 10 | 5 |
| 4 | 15 | 10 |
This result groups requested items by its ID and return the Requested Quantity, also SUM the already ordered ammounts of OrderItems for this RequestItem
Given this result i can calculate pending items also.
I've managed to solve this issue building two Queries one to get RequestedItems and one to get OrderedItems and matching these two with PHP but i think it is possible to do this on the database side.
If anyone can help me with this it would be much appreciated.
Thanks.
UPDATE #1:
I have issues with subqueries inside a join when using the QueryBuilder, but i managed to build a working query, adding the subquery in the join condition.
I'm adding my working query below but i still need to do multiple checks to see if it is really my answer.
You can get the example result by executing
SELECT ri.ID AS RequestItemsID, ri.Qtty AS QttyRequested,
SUM(oi.qtty) AS QttyOrdered
FROM RequestItems ri
INNER JOIN Order AS o ON o.RequestId = ri.RequestId
INNER JOIN OrderItems AS oi ON oi.OrderId = o.ID
WHERE ri.RequestId = 2 AND o.State = 1
GROUP BY ri.RequestId, o.State
It seems Doctrine doesnt support subqueries in the JOIN part of the query but i managed to add a subquery in the condition part of my JOIN.
Based on https://groups.google.com/forum/#!topic/doctrine-user/0rNbXlD0E_8 this can be solved with IN(SUBQUERY)
This is what is working right now given the example in the OP
SELECT ri.ID AS RequestItemsID, ri.Qtty AS QttyRequested, COALESCE(SUM(oi.Qtty), 0) AS QttyOrdered
FROM RequestItems AS ri
LEFT JOIN OrderItems AS oi ON oi.RequestItemsID = ri.ID AND oi.OrderID IN (
SELECT o.ID FROM Order AS o WHERE o.State = 1 AND o.RequestID = 2
)
WHERE ri.RequestID = 2
GROUP BY ri.ID;

PHP/MYSQL group and count by distinct dates and users

I'm trying to wrap my head around how to get a distinct count of days a user logged in, when the db has each login session stored with a time and date stamp (DATETIME column). EG:
USERID | TIME | BOUGHT
--------------------------
4 | 2012-07-16 04:44:52 | 3
4 | 2012-07-16 04:45:52 | 2
5 | 2012-07-16 04:54:52 | 5
4 | 2012-07-18 04:44:52 | 3
4 | 2012-07-18 04:45:52 | 2
4 | 2012-07-21 04:54:52 | 5
I want to search for how many times user 4 bought from the site - and the query should return 3 (because user 4 visited the site a total of 3 days). Do I have to use a PHP/MYSQL combination or can I do it in SQL?
SELECT USERID, COUNT(DISTINCT DATE(TIME)) FROM my_table GROUP BY USERID
See it on sqlfiddle.

Calculating total quantity of equipments for a date range

Project: I am working on a project which is about some rooms and equipments using in the rooms. The software is about scheduling the equipments in the rooms. In other words, it is a reservation software that reserves selected equipments in separate rooms for needed dates and times ranges. I have many tables in MYsSQL database working with Php but I will mention the tables my question is about. The tables I will relate my questions are equipment table (Table A), schedule table (Table B) and equipments using in the related schedule (Table C).
Table A: equipment list table
eqid | eqName | available|
1 | book | 90 |
2 | pen | 82 |
3 | computer | 25 |
In table A; eqid represents unique id of an equipment, eqName represents name of an equipment, available represents total available equipments existing.
Table B: schedule table
scheduleid | startDate | endDate | startTime | endTime | office |
1 | 2012-08-27 | 2012-08-27 | 08:30:00 | 10:00:00 | room1 |
2 | 2012-08-27 | 2012-08-27 | 09:30:00 | 11:00:00 | room3 |
3 | 2012-08-28 | 2012-08-30 | 08:30:00 | 12:00:00 | room2 |
4 | 2012-08-29 | 2012-08-31 | 11:30:00 | 14:00:00 | room1 |
5 | 2012-08-28 | 2012-08-28 | 10:30:00 | 14:00:00 | room3 |
6 | 2012-08-27 | 2012-08-30 | 08:30:00 | 10:00:00 | room4 |
7 | 2012-08-27 | 2012-08-27 | 10:30:00 | 12:00:00 | room4 |
8 | 2012-08-27 | 2012-08-30 | 08:30:00 | 11:00:00 | room6 |
9 | 2012-08-27 | 2012-08-27 | 10:30:00 | 12:00:00 | room5 |
In table B; scheduleid represents unique id for a schedule, startDate and endDate are date range for a schedule, startTime and endTime time range for a schedule, office means that where the schedule will take place. Let me give an example here. Scheduleid 1 means there is a reservation on 27th of august 2012, Monday and it is from 08.30 to 10:00. As it start and end on same day this is just one day reservation in room1. However, Scheduleid 3 means there is a reservation starts on 28th of august 2012, Tuesday and goes on until 30th of august 2012, Thursday at 08:30-12:00... in other words, it lasts for 3 days and everyday from 08:30 to 12:00... So there is a reservation from Tuesday to Thursday at 08:30 to 12:00 in room2... I hope this is clear.
Table C: equipments using in the related schedule
Autoid | scheduleid | eqid | amountInSch|
1 | 1 | 1 | 2 |
2 | 1 | 2 | 3 |
3 | 1 | 3 | 1 |
4 | 2 | 1 | 1 |
5 | 2 | 2 | 1 |
6 | 2 | 3 | 2 |
7 | 3 | 2 | 1 |
8 | 3 | 3 | 3 |
9 | 4 | 2 | 1 |
10 | 4 | 3 | 1 |
11 | 5 | 1 | 1 |
12 | 6 | 1 | 1 |
13 | 6 | 3 | 2 |
14 | 6 | 2 | 4 |
15 | 7 | 1 | 5 |
16 | 7 | 2 | 6 |
17 | 8 | 2 | 1 |
18 | 9 | 1 | 8 |
19 | 9 | 2 | 5 |
20 | 9 | 3 | 6 |
In table C: Autoid represents unique automatic id generated by auto-increment, scheduleid comes from Table B, eqid comes from Table A, amountInSch represents how many (amount) equipment will use in the related schedule. I want to give an example here. Scheduleid 1 in Table C, there are 3 rows. This means that scheduleid 1 related in TAble B will use 2 books (eqid 1), 3 pens (eqid 2) and 1 computer (eqid 3) in room1 specified dates and times in table B . Another example is that scheduleid 3 in Table C is related 2 rows. It means that 1 pen (eqId 2) and 3 computers (eqId 3) will be using in room2 from 27th to 30th of august 2012 everyday from 08:30 to 12:00.
The above is the explanation and give some information about the project. The table rows are not permanent. When you make a reservation, there will be a new row in Table B and if it is selected an equipment, there will be new rows in table C...
The Question:
I want to calculate left amount of a specific equipment when I supply eqId, startDate, endDate, startTime and endTime...
An example:
eqId: 1 (book)
startDate: 2012-08-27
endDate: 2012-08-27
startTime: 08:30:00
endTime: 12:00:00
Result should be: 14 books used in schedule and 76 left available books
Because: if you look scheduleIds and related eqIds, you will only see 1, 2, 6, 7, 9 scheduleIds related to my query(dates and eqId). If you sum the all amount of related in Table C, you will get the wrong result. In other words, related amounts for eqId(1-book) and for 1, 2, 6, 7, 9 scheduleIds are 2, 1, 1, 5, 8 respectively. So if you sum them you will get 17 which is wrong. Because, 1 and 9 schedule don't intersect each other in terms of start and end Times, and 6 and 7 don't intersect each other either. as a result of them 2 stays lonely and can be count separately. We must consider 1 and 9 as summed 8 because 8 is bigger than 2. it is same for 6 and 7, considered as 5 because of 5 is bigger than 1...
So folks! I am not sure how I can sum/ this in programming algorithm. Is there a way to do in SQL or do I have to use PHP and Mysql together? and How?
Cheers!
SQLFiddle Records
I started with the following SQL to gather all date ranges that intersect with the given range:
SELECT MAX(available) - IFNULL(SUM(amountInSch), 0)
FROM Table1
LEFT JOIN Table3 USING (eqid)
LEFT JOIN Table2 USING (scheduleid)
WHERE DATE(startDate) <= '2012-08-27' AND DATE(endDate) >= '2012-08-27'
AND endTime > '08:30' AND startTime < '12:00'
AND eqid = 1
Fiddle
This is only the first part. Next up you have to work out the possible overlaps; this wouldn't be practical to do with SQL, so I would suggest to do this in PHP.
The generic algorithm I would pick is unfortunately O(n**2), it goes like this:
create a timeline (demarcated by each day) with time as the horizontal axis
iterate over every date/time range and mark the time of its left and right edge to create time segments of every possible permutation.
using the segments, you sum vertically for overlaps and you take the daily maximum across.
Hope that helps.

Categories