Repeat records according to a quantity field - ms-access

I have an Excel sheet which I receive from my customer and I get imported to Access and I would call that table [tblCustomer] and that would look something like this:
ProductID Name Expire date SumofQty
------------ ----------- --------------- --------
3 Flour 13-Dec-2013 6
6 Meat 20-Jan-2014 10
So the table contain maybe 100 items. I want in the same table or another table to copy the same record 6 times as per SumofQty and than the next record copy it 10 times and so on.
I need this cause I will create labels for each product right now I'm doing manually.

You can do that in a Query quite easily by using a "Numbers table". Create a table named [Numbers] in your database consisting of a single field named [n] that has a field type of Numeric (Long Integer). Create rows in that table with values 1, 2, 3, ... up to a number that well exceeds the largest value you ever expect to see in [tblCustomer].[SumofQty]. In my test I used 2500, so my [Numbers] table looks like
n
----
1
2
3
...
2499
2500
Then, for sample data in table [tblCustomer]
ProductID Name Expire date SumofQty
--------- ----- ----------- --------
3 Flour 2013-12-13 6
6 Meat 2014-01-20 10
the query
SELECT tblCustomer.*
FROM
tblCustomer
INNER JOIN
Numbers
ON Numbers.n <= tblCustomer.SumofQty
returns
ProductID Name Expire date SumofQty
--------- ----- ----------- --------
3 Flour 2013-12-13 6
3 Flour 2013-12-13 6
3 Flour 2013-12-13 6
3 Flour 2013-12-13 6
3 Flour 2013-12-13 6
3 Flour 2013-12-13 6
6 Meat 2014-01-20 10
6 Meat 2014-01-20 10
6 Meat 2014-01-20 10
6 Meat 2014-01-20 10
6 Meat 2014-01-20 10
6 Meat 2014-01-20 10
6 Meat 2014-01-20 10
6 Meat 2014-01-20 10
6 Meat 2014-01-20 10
6 Meat 2014-01-20 10

Here's the solution using Erik von Asmuth's comment which pointed to an answer originally created by Gustav.
SELECT t.*
FROM tblCustomer AS t
INNER JOIN (SELECT DISTINCT
[Hundreds]+[Tens]+[Ones] AS Factor,
100*Abs(Hundo.id Mod 10) AS Hundreds,
10*Abs(Deca.id Mod 10) AS Tens,
Abs(Uno.id Mod 10) AS Ones
FROM
msysobjects AS Uno,
msysobjects AS Deca,
msysobjects As Hundo
WHERE Abs(Deca.id Mod 10) <> 0
or Abs(Uno.id Mod 10) <> 0
or Abs(Hundo.id Mod 10) <> 0) AS sq on sq.Factor <= t.SumofQty
I added the hundreds column as well because I think I'm probably going to need it. My method also filters out 0 in the sub query, otherwise I was getting 2 rows for things with a quantity of 1.

Related

how to generate student attendance percentage per course, when they have specific day in a week

hi guys i really newbie in sql, i need help to generate percentage of attendance, here is the table:
Table Schedule
Schedule_ID Course_ID Lecture_ID Start_Date End_Date Course_Days
1 1 11 2019-09-09 2019-12-08 2,4,6
2 3 4 2019-09-09 2019-12-08 3,4
3 4 13 2019-09-09 2019-12-08 2,5
4 5 28 2019-09-09 2019-12-08 3
5 2 56 2020-01-27 2020-04-26 2,4
6 7 1 2020-01-27 2020-04-26 4,5
7 1 11 2020-01-27 2020-04-26 2,4,6
8 7 22 2020-01-27 2020-04-26 2,3
9 8 56 2020-01-27 2020-04-26 5
10 3 37 2020-01-27 2020-04-26 5,6
Reference of days of week used in this data.
1: Sunday, 2:Monday, 3:Tuesday, 4:Wednesday, 5:Thursday, 6:Friday, 7:Saturday
Table course_attendance
ID STUDENT_ID SCHEDULE_ID ATTEND_DT
1 1 2 2019-09-10
2 1 2 2019-09-11
3 1 2 2019-09-17
4 1 2 2019-09-18
......
46 2 1 2019-12-02
47 2 1 2019-09-11
48 2 1 2019-09-18
49 2 1 2019-09-25
50 2 1 2019-10-09
51 2 1 2019-10-16
....
111 6 1 2019-09-23
112 6 1 2019-09-30
113 6 1 2019-10-07
114 6 1 2019-10-14
table student
ID NAME
1 Jonny
2 Cecilia
3 Frank
4 Jones
5 Don
6 Harry
i need to show up like this :
STUDENT_ID NAME Course_ID Attendance rate
1 Jonny 1 82%
2 Cecilia 1 30%
3 Frank 3 100%
4 Jones 2 100%
5 Don 2 25%
6 Harry 4 40%
EDIT this my last step to get percentage:
result:
with main as (
select ca.STUDENT_ID,
ca.SCHEDULE_ID,
s.COURSE_ID,
co.NAME as course_name,
st.NAME,
count(ca.ID) as total_attendance,
((CHAR_LENGTH(s.COURSE_DAYS) - CHAR_LENGTH(REPLACE(s.COURSE_DAYS , ',', '')) + 1) * 13) as attendance_needed
from univ.course_attendance ca
left join univ.schedule s on ca.SCHEDULE_ID = s.ID
left join univ.student st on ca.SCHEDULE_ID = st.ID
left join univ.course co on ca.SCHEDULE_ID = co.ID
group by ca.STUDENT_ID, ca.SCHEDULE_ID
)
select *,total_attendance/attendance_needed as attendance_percentage
from main
order by 1,2;
This can be done following three steps.
Step 1: Calculate the total number of days a particular course of a schedule has. It's a good thing the start_date is always on Monday and the end_date is always on Sunday, which makes the week complete and saves some trouble. By calculating the total number of weeks a course go through and the number of days a week has for that course, we can get the total number of days a particular course of a schedule has.
Step 2:Calculate the total number of days a student for a schedule. This is done fairly easily. Note: As the majority part of the table has been skipped and the OP has yet to provide the complete data set, I could only have 14 existing rows provided.
Step 3: Calculate the percentage for the attendance using the result from the above two steps and get other required columns.
Here is the complete statement I wrote and tested in workbench:
select t2.student_id as student_id,`name`,course_id, (t2.total_attendance/t1.total_course_days)*100 as attendance_rate
from (select schedule_id,course_id,
length(replace(course_days,',',''))*(week(end_date)-week(start_date)) as total_course_days
from Schedule) t1
JOIN
(select count(attend_dt) as total_attendance,student_id,schedule_id
from course_attendance group by student_id, schedule_id) t2
ON t1.schedule_id=t2.schedule_id
JOIN
student s
ON t2.student_id=s.id;
Here is the result set ( the attendance_rate is not nice due to the abridged course_attendance table):
student_id, name, course_id, attendance_rate
2, Cecilia, 1, 15.3846
6, Harry, 1, 10.2564
1, Jonny, 3, 15.3846

Sum of all child and assign to parent in hierarchical data in MySql

I have a 2 Mysql tables like 1.Product(This table is hierarchical or recursive) and 2.Sales table in this will store sale id and product id. I need to show parent product with the sum of all hierarchical child product.
Product table having data like,
id name parent_id
1 Necklace NULL
2 Ring NULL
3 Earing NULL
4 Choker 1
5 Long Necklace 1
6 Short Necklace 1
7 2-Line 5
8 3-Line 5
9 Mango 5
10 Green 7
11 Red 7
12 White 7
13 Stud 3
Sales table will have data like,
id product_id no_of_pcs weight rate
1 10 5 40 35000
2 12 8 50 50000
3 9 2 20 25000
4 6 1 8 25000
5 13 2 16 22000
Now I'm trying the result as,
Product sale_pcs tot_pcs sale_wt sale_rate
1 Necklace 16 118 135000
3 Earing 2 16 22000
Now I'm using mysql query inside php recursive function by using product table. By using this even recursive function all the products need to check with sales table. This will happening performance issue. Could you please help any one to solve this issue whether this possible by doing in query itself

MySQL sum column and display last row in column

I have a table of users,subscription packages and various user subscriptions.
I need to fetch a sum of all subscription cost and display the latest/last subscription. The latest subscription is the subscription
with the highest subscription_id. How can I write my query? My tables are listed as below.
Users table
user_id name
1 John
2 Jane
3 Matthew
Subscription Packages table
package_id package_name
1 Basic
2 Advanced
3 Premium
User Subscriptions
subscription_id user_id package_id subscription_cost date
1 1 1 2 2014-04-01
2 2 1 2 2014-04-01
3 3 1 2 2014-04-01
4 1 1 2 2014-05-01
5 1 2 3.5 2014-06-01
6 2 2 3.5 2014-06-01
7 2 2 3.5 2014-07-01
8 1 3 5 2014-07-01
9 3 2 5 2014-07-01
10 2 2 3.5 2014-08-01
11 1 1 2 2014-08-01
My results should be like so
name total_costs latest_package
John 14.5 Basic
Jane 12.5 Advanced
Matthew 7 Premium
Because you need to do an aggregation anyway, I would go for the group_concat()/substring_index() trick:
select u.user_id, u.name, sum(subscription_cost) as total_costs,
substring_index(group_concat(p.package_name order by us.date desc), ',', 1) as latest_package
from usersubscriptions us join
users u
on us.user_id = u.user_id join
packages p
on us.package_id = p.package_id
group by u.user_id;
This assumes that no package names have commas. It is also subject to default limits on the length of the result of group_concat() -- but this method often works in practice.

How to select more rows with MySQL after sorting?

I have a table which have 10 results. Let's say the following:
id user number
-- ---- ------
1 user1 10
2 user2 5
3 user3 30
4 user4 45
5 user5 5
6 user6 22
7 user7 10
8 user8 40
9 user9 90
10 user10 65
I basically want to sort them, by the 'number' value.
So it should be something like this:
SORT id user number
---- -- ---- ------
1 2 user2 5
2 5 user5 5
3 1 user1 10
4 7 user7 10
5 6 user6 22
6 3 user3 30
7 8 user8 40
8 4 user4 45
9 10 user10 65
10 9 user9 90
After it's been sorted, I want to select * from (for example) the one with id = 6 (which's number is 22) and 2 other results which is above it (in this case: id = 7 and 1) and 2 other results under it (in this case: id = 3 and 8).
So the return result should be something like this, when I'm searching for id = 6:
SORT id user number
---- -- ---- ------
3 1 user1 10
4 7 user7 10
5 6 user6 22
6 3 user3 30
7 8 user8 40
I could esaily do this on server side, if I select everything, however there will be a huge data amount in here, so I'd rather just select those, which are appropriate to my search.
Is there any way to do this with MySQL?
Here is a typical way to get what you want:
select t.*
from ((select t.*
from table t
where number <= (select number where id = 6 limit 1)
order by number desc
limit 3
) union all
(select t.*
from table t
where id > (select number where id = 6 limit 1)
order by number asc
limit 2
)
) t
order by number;
This assumes that when duplicates appear, you still want 5 rows output. It also assumes that less than five rows is ok for the first two or last two rows. An index on id would help performance of this query.
Get UNION of 2 queries:
Get all records <= the desired number, in your case 22. Sort them in descending order and get top 3 results.
Get all records > the desired number in ascending order and get top 2 results
Get the UNION of these 2 results and order them in ascending order
HTH
EDIT: My idea to post this answer was to give an algorithm on how to approach such queries. Instead of selecting on number, you can get all records based on id and then UNION them.

MYSQL: Select from table A, based on seen date of user in Table B

OK I have three tables RegionName(Key, Name), Players(Key, Name, Seen), and regionplayers(key, regionkey, playerkey)
there is more to each table but it isn't needed so to make this easier i have only included what is needed.
I have regions, and a player can be added to a region, a region may have many players, and players can be on many regions. there are 1680 regions, 900ish players and about 3500 entries in the table linking them together.
I want to be able to find regions, where none of the players have been seen in 8+ days.
what I have atm is:
SELECT RegionName.*, RegionPlayer.*, Players.*
FROM RegionName
JOIN RegionPlayer
ON RegionPlayer.Regionkey= RegionName.Key
JOIN Players
ON Players.Key = RegionPlayer.Playerkey
WHERE
( Seen <= (NOW() - INTERVAL 8 DAY ) ) )
AND RegionName.Perent = 'none'
ORDER BY `RegionName`.`Name` ASC,
Players.Seen DESC
currently I get all the regions where people who have not been seen for 8+ days, so if a region has 1 player who hasn't been seen, it is returned, but I only want regions where everyone has been away for 8+days.
Here is a sort of sampling if the data for each of the tables, this was done by me just now. because its just easier then trying to pull enough data that makes the point, and should give the results I want.
RegionName
key Name
1 regionone
2 regiontwo
3 regionthree
4 regionfouor
5 regionfive
Players
Key Name Seen
1 jack 2014-03-21 12:43:46
2 joe 2014-03-26 12:43:46
3 bob 2014-03-20 12:43:46
4 bill 2014-03-19 12:43:46
5 dave 2014-03-17 12:43:46
6 tina 2014-03-28 12:43:46
7 tony 2014-03-29 12:43:46
8 george 2014-03-15 12:43:46
9 sam 2014-03-18 12:43:46
10 frank 2014-03-18 12:43:46
RegionPlayer
key Regionkey PlayerKey
1 1 1
2 1 4
3 1 5
4 2 1
5 2 4
6 2 2
7 3 6
8 3 1
9 3 7
10 4 1
11 4 8
12 4 7
13 4 5
14 5 3
So I should based on this data get back regions regionone, & regionfive.
SELECT RegionName.*, RegionPlayer.*, Players.*
FROM RegionName
JOIN RegionPlayer
ON RegionPlayer.Regionkey= RegionName.Key
JOIN Players
ON Players.Key = RegionPlayer.Playerkey
WHERE RegionName.Perent = 'none'
GROUP BY RegionName.Name
HAVING
SUM( Seen > (NOW() - INTERVAL 8 DAY ) ) =0
ORDER BY `RegionName`.`Name` ASC,
Players.Seen DESC