I've got a problem with this query:
$query="select *,max(revision) as maxrev
from oda
where name_company_app='$_SESSION[name_main]'
and year(date_emitted)='$_SESSION[year_ref]'
group by n_order
order by n_order DESC";
Inside DB I have a table (oda) where there are records with a order number (n_order) a revision of the order expressed with numbers (revsion=0-first|1-second|2-third eccetera...) with different date... the piont is, I sholud get an array with all orders of a certain company(name_company_app) showing only the last revision (from here the max()) of an order.
The point is that every new year the software starts counting n_orders from 1 so I have 300 orders of 2014 starting from 1 to 300 and 25 orders of 2015 starting from 1 to 25.. when I use "group by" it removes duplicates of n_orders selecting the max revision.
Result? I have first 25 numbers wrong (mixed by 2014 and 2015 depending the revision) and in total only 300 even they should be 325.
Any suggestion how may I change the query for showing all the data?
Related
I need to generate beginning balance for the selected month. for example, I'm having a list of pre-allocated serial numbers/ids/rows 1000 to 1999. In February I'm using 800 numbers (from id 1000-1799). Thus, my next months beginning balance would be 200.
In my DB I'm having three relevant columns: id, created_date and updated_date.
If I use only 50 numbers in March (1800-1849), then beginning balance for April is 150 (I already used up 850 of the pre-allocated 1000 ids). How to query the DB to fetch the number of remaining pre-allocated ids?
This example is based on the amount of information you provided and assumes you don't need to filter by user id or any other data, but that you do have a numeric row id.
SELECT (1000 - COUNT(*)) AS balance FROM table_name WHERE id BETWEEN 1000 AND 1999
If that is not the case, then please add the result of the
explain table_name command, where you substitute table_name with the actual name of the table.
So I have a table that looks like this:
Person Product Date Quantity
1 A 1/11/2014 1
2 A 1/11/2014 2
1 A 1/20/2014 2
3 A 1/21/2014 1
3 B 1/21/2014 1
1 A 1/25/2014 1
I want to find the Count of Quantity where Product is A and Person has a Count > 1 WITHIN ANY SLIDING 30 DAY RANGE. Another key is that once two records meet the criteria, they should not add to the count again. For example, Person 1 will have a count of 3 for 1/11 and 1/20, but will not have a count of 3 for 1/20 and 1/25. Person 2 will have a count of 2. Person 3 will not show up in the results, because the second product is B. This query will run within a specific date range also (e.g, 1/1/2014 - 10/27/2014).
My product is written in MySQL and PHP and I would prefer to do this exclusively in MySQL, but this seems more like an OLAP problem. I greatly appreciate any guidance.
Another key is that once two records meet the criteria, they should not add to the count again.
This is not relational. In order for this to be meaningful, we have to define the order in which records are evaluated. While SQL does have ORDER BY, that's for display purposes only. It does not affect the order in which the query is computed. The order of evaluation is not meant to matter.
I do not believe this can be expressed as a SELECT query at all. If I am correct, that leaves you with plSQL or a non-SQL language.
If you're willing to drop this requirement (and perhaps implement it in post-processing, see below), this becomes doable. Start with a view of all the relevant date ranges:
CREATE VIEW date_ranges(
start_date, -- DATE
end_date -- DATE
) AS
SELECT DISTINCT date, DATE_ADD(date, INTERVAL 30 day)
FROM your_table;
Now, create a view of relevant counts:
CREATE VIEW product_counts(
person, -- INTEGER REFERENCES your_table(person)
count, -- INTEGER
start_date, -- DATE
end_date -- DATE
) AS
SELECT y.person,
sum(y.quantity),
r.start_date,
r.end_date
FROM date_ranges r
JOIN your_table y
ON y.date BETWEEN r.start_date AND r.end_date
GROUP BY y.person
HAVING sum(y.quantity) > 1;
For post-processing, you need to look at each row in the product_counts view and look up the purchase orders (rows of your_table) which correspond to it. Check whether you've seen any of those orders before (using a hash set), and if so, exclude them from consideration, reducing the count of the current item and possibly eliminating it entirely. This is best done in a procedural language other than SQL.
So I have a single table inside which I have a score system for points. It looks something along this line:
Columns:
ID Name Date Points
1 Peter 2014-07-15 5
2 John 2014-07-15 6
3 Bill 2014-07-15 3
and so on...
Everyday, the new results are being put into the table with the total amount of points acumulated, however in order to be able to get historic values, the results are put into new rows. So on the 2014-07-16, the table will look like this:
ID Name Date Points
1 Peter 2014-07-15 5
2 John 2014-07-15 6
3 Bill 2014-07-15 3
4 Peter 2014-07-16 11
5 John 2014-07-16 12
6 Bill 2014-07-16 3
However sometimes when a player doesn't take part for the whole day and doesn't get any points, he will still be added, but the points will remain the same (here this is shown by the case of Bill).
My question is how to count the number of each type of players (active - Peter and John ie when the points value changes from one date to another and inactive - Bill ie when the points value stays the same).
I have managed to get this query to only select players who do have the same value, but it's giving me the list of players rather than the count. Although I could potentialy be wrong with this query:
SELECT Points, name, COUNT(*)
FROM points
WHERE DATE(Date) = '2014-07-15' OR DATE(Date) = '2014-07-16'
GROUP BY Points
HAVING COUNT(*)>1
I'm not sure how to count the number of rows (could do a bypass trick with PHP getting the number of rows, but interested in SQL only) or how to invert it, to get a count of players who have a different score (again, could get total of rows and then subtract the above number, but not interested in that either - I'd prefer the SQL).
Regards and thanks in advance.
You are pretty close.
If you have at most one row per "player" per "date", you could do something like this:
SELECT SUM(IF(c.cnt_distinct_points<2,1,0)) AS cnt_inactive
, SUM(IF(c.cnt_distinct_points>1,1,0)) AS cnt_active
FROM ( SELECT p.name
, COUNT(DISTINCT p.points) AS cnt_distinct_points
FROM points p
WHERE DATE(p.Date) IN ('2014-07-15','2014-07-16')
GROUP BY p.name
) c
The inline view query (aliased as c) gets a count of the distinct number of "points" values for each player. We need to "group by" name, so we can get a distinct list of players, along with an indication whether the points value was different or not. If all of the non-NULL "points" values for a given player are the same, COUNT(DISTINCT ) will return a value of 1. Otherwise, we'll get a value larger than 1.
The outer query processes that list, collapsing all of the rows into a single row. The "trick" is to use expressions in the SELECT list that return 1 or 0, depending on whether the player is "inactive", and perform a SUM aggregate on that. Do the same thing, but a different expression to return a 1 if the player is "active".
If the count of distinct points for a player is 1, we'll essentially be adding 1 to cnt_inactive. Similarly, of the distinct points for a player is greater than 1, we'll be adding 1 to the cnt_active.
If this doesn't make sense, let me know if you have questions.
NOTE: Ideally, we'd avoid using the DATE() function around the p.Date column reference, so we could enable an appropriate index.
If the Date column is defined as (MySQL datatype) DATE, then the DATE() function is unnecessary. If the Date column is defined as (MySQL datatype) DATETIME or TIMESTAMP, we could use an equivalent predicate:
WHERE p.Date >= '2014-07-15' AND p.Date < '2014-07-16' + INTERVAL 1 DAY
That looks more complicated, but a predicate of that form is sargable (i.e. MySQL can use an index range scan to satisfy it, rather than having to look at every row in the table.)
For performance, we'd probably benefit from an index with leading columns of name and date
... ON points (`name`,`date`)
(MySQL may be able to avoid a "Using filesort" operation for the GROUP BY).
I would solve this problem by looking at the previous number of points and then doing a comparison:
select date(date), count(*) as NumActives;
from (select p.*,
(select p2.points
from points p2
where p2.name = p.name and p2.date < p.date
order by p2.date desc
limit 1
) as prev_points
from points p
) p
where prev_points is NULL or prev_points <> points;
Of course, you can add a where clause to get the count for any particular day.
I'm building a web site for marketing company. As per their requirement, when a customer makes a booking. A certain amount of bonus is distributed between employees based on
their hierarchy. The distribution starts from 60 days after booking and bonus is given
for 24 months.
The tables are
bookings
bid book_date
1 2012-05-09
2 2012-05-10
bonus
bid empid amount
1 1 300
1 2 400
2 2 300
2 3 400
Is it possible to write mysql views that generates monthly bonus an employee gets
for every month. I didn't find solution on how to make update with mysql view. Any hint
will of great help.
Instead of view, I would suggest is write mysql function which will return the bonus by accepting the employee ID.
Using mysql function you will have more room to write logic and PL/SQL.
Inner join on bid and filter to only include eligible bonuses by comparing the book date to today's date. If today's date is less than 60 days after or more than 24 months plus 60 days after the original book date, exclude it. (You can go to mySQL.com to learn more about how to manipulate dates in mySQL. I forget...)
You will be left with multiple rows containing only emp id and amount. In the second round, use a "select sum(amount) from (...put your other query here...) group by empid" to get the aggregate bonus per employee.
This approach (and I think any solution) requires a nested SQL statement, and so if you're not comfortable with that syntax you can use that term to explore in google or SO. Cheers!
I am using MySQL and PHP. I have a table that contains the columns id and quantity. I would like to retrieve the id of the row that is the last to sum quantity as it reaches the number 40 at sum. To be more specific. I have 3 rows in the database. One with quantity 10, one with quantity 30 and one with quantity 20. So if I sum the quantities to have the result 40, I would sum up the first two witch means: 10 + 30 = 40. That way, the last Id that is used to sum the number 40 is 2. I just want to know the id of the last row that is used to complete the sum of 40.
I would give further details if asked. THANK YOU!!
Let me put it this way:
I really have 6 products in my hand. The first one came to my possession on the date of 10, the next 3 came on the date of 11 and the last 2 came on 12.
Now, I want to sell 3 products from my stock. And want to sell them in the order that they came. So for the customer that wants 3 products I would sell him the product that came on 10 and 2 products from the ones that came on 11.
For the next customer that wants 2 products, I would sell him one product from the date of 11 that remains from the last order of 3 products, and another one from the ones on 12.
The question is how would I know which price had each product I sold ? I thought that if I can find out which rows sums up every requested quantity, I would know where to start the sum every time I want to deliver an order. So first I would look which rows sums up 3 products and keep the entry id. For the next order I would start the count from that ID and sum until it sums up the second order of 2 products and so on. I thought that this way, I can keep track of the incoming prices that each product had. So I won't sell the products from the date of 12 at a price made up using the first prices.
I hope you understand. I just need to know what price had any of my products so I would know that the first products would have one price but as the product prices raises, I must raise my prices too...So the last products that came must be sold for a higher price. I can only achieve that if I keep track of this...
Thank you very much.
Nobody ? Or, even easier: MySQL should select the needed rows for SUM(quantity) to be higher or equal with 40 for example. And then to get me the id of the last row that participated at the sum process.
Have a third column with a running total. Then you can simply return the last row where the running total <= your target value.
So your table should look like:
ID Quantity RunningTotal
1 10 10
2 30 40
3 20 60
NOTE: If you delete a row in the table, remember to update all subsequent rows RunningTotal -= DeletedRow.Quantity!
I don't understand your question too well. Can you try rewording it more properly? From what I interpret, here's the structure of your database:
ProductID ArrivalDate
1 10
2 11
3 11
4 11
5 12
6 12
Now you are asking, "how would I know which price had each product I sold"? Which sorta confuses me, since each value in the database has no price attribute. Shouldn't your database look like this:
ProductID ArrivalDate Price
1 10 100
2 11 200
3 11 300
4 11 300
5 12 400
6 12 400
Personally, I think your idea to find out price sold is flawed. It would make more sense to add a few more fields to your database:
ProductID ArrivalDate Price InStock DateSold
1 10 100 Yes 17
2 11 200 Yes 17
3 11 300 Yes 18
4 11 300 Yes 18
5 12 400 no
6 12 400 no
In changing your database, you can easily keep track of when a product arrives, the date sold, its price, maybe quantity (I can't tell if its an actual field or not).
Furthermore, you can simplify and make your life easier by separating the sql queries, or even adding some code to do some of the work for you.
Relying on table ID's is probably a bad idea for this, but if that is how it is really done, you could try something like this (not tested):
SELECT yourTableA.id
FROM yourTable AS yourTableA
JOIN yourTable AS yourTableB
WHERE ( yourTableA.value + yourTableB.value ) = 40
AND yourTableA.id != yourTableB.id
ORDER BY yourTableA.id
This type of solution will only work if your expecting that you only need two rows ever to equal your target sum. Since this is most likely not the case, your best bet is probably to try and get all of the rows and do this programaticly on the returned data.
The Running Total solution posted by lc is also a good option although I generally try to avoid storing calculated data unless I absolutely have to.
Based on the updated information from this request, I have an alternate answer.
It doesn't sound so much like you care about the inventory. You care more about when the products came in.
SELECT *
FROM product
ORDER BY product.receivedData
Process each record as they come in, store the price for that record, and keep going for as long as you need to until you reach the number of items you need. You should end up with a list of items, the number of inventory at that level and the price at that level.