I have data that looks like this:
+----+------------+------------+------------+
| id | join_date | start_date | end_date |
+----+------------+------------+------------+
| 1 | 2005-11-01 | 2005-11-01 | 2014-04-11 |
| 2 | 2007-10-29 | 2007-10-29 | 2011-10-29 |
| 3 | 2005-11-17 | 2005-11-17 | 2014-11-15 |
| 4 | 2006-12-30 | 2009-12-30 | 2013-12-29 |
| 5 | 2005-12-03 | 2011-03-11 | 2013-11-29 |
+----+------------+------------+------------+
And the information about the fields above are as follows:
join_date is the date the account was first created.
start_date is the date of the start of an unbroken membership (eg, if
a member joins in 2005, lapses in 2006, and renews in 2008,
start_date would have a date in 2008).
end_date is when membership will lapse (whether a time in the future
or past).
I've been trying to come up with a query that will get me a count of all active members through time (the result being a time series graph of active accounts).
Nothing I've tried has really worked, and I think I just need another perspective. Any suggestions?
Related
I am working on railway transport.
I have the following tables:
DAY table
| - id | name |
| 1 | sunday |
| 2 | monday |
| 3 | tuesday|
station table
|- id | name |
| 1 | zaria |
| 2 | kano |
| 3 | minna |
route table
| - id | source_station_id | destination_station_id|
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 2 | 3 |
| 4 | 3 | 2 |
| 3 | 3 | 1 |
departure table
| route_id | day_id | departure_time |
| 1 | 2 | 07:00 hrs |
| 1 | 3 | 07:00 hrs |
| 3 | 2 | 15:30 hrs |
route_id, day_id, source_station_id, destination_station_id are all foreign keys referenced from route, day, and station table respectively.
Now... how do I use sql to fetch from these tables..
output to look like the table below.
| source | destination | day | departure_time |
You want to use a JOIN:
SELECT
source.name AS source,
destination.name AS destination,
day.name AS day,
departure.time AS departure_time
FROM departure
JOIN station AS source
ON departure.source_station_id = source.id
JOIN station AS destination
ON departure.source_station_id = destination.id
JOIN day
ON departure.day_id = day.id
WHERE
# any specific criteria you may have, like:
departure.day_id = 1 # for a sunday
Should do it. For more information see MySQL JOIN Syntax
That said, this is a pretty standard question, and I would not be surprised to see it get voted down.
Further, from a structural point of view, you would really be better off storeing the "day" as a DATETIME, and converting this to and from a Human Readable date string on the fly.
As it stands, since you are only doing the day of the week, you have no way of differentiating between this week and last or last year. Have a look at the bottom-half of this comment, where I start talking about spanning periods of time, and discuss the use of DATETIME. Using native data-types is a preferable, both for performance, and ease of use.
Imagine an unordered table set up as below:
+----+------------+----------+-----------+
| ID | Project | Resource | StartDate |
+----+------------+----------+-----------+
| 1 | ExtraParts | Mark | 24/01 |
| 2 | ExtraParts | Sam | 22/01 |
| 3 | TimeLabour | Sally | 19/01 |
| 4 | TimeLabour | Sarena | 23/01 |
| 5 | Runway | Olly | 14/02 |
| 6 | Runway | Mary | 14/05 |
+----+------------+----------+-----------+
I would like to order by the earliest StartDate for each project, but still group the resources from each projects together(not sure if im explaining this right, but below is what I would like to achieve)
+----+-------------+-----------+-----------+
| ID | Project | Resource | StartDate |
+----+-------------+-----------+-----------+
| 1 | TimeLabor | Sally | 19/01 |
| 2 | TimeLabor | Sarena | 23/01 |
| 3 | ExtraParts | Sam | 22/01 |
| 4 | ExtraParts | Mark | 24/01 |
| 5 | Runway | Olly | 14/02 |
| 6 | Runway | Mary | 14/05 |
+----+-------------+-----------+-----------+
If I do ORDER BY StartDate, Project then the result will have jumbled up the projects. If i ORDER BY Project, StartDate then the result will be sorted alphabetically by project first and then sort by date within the same project(if that makes sense). As stated above, I would like to order by the earliest StartDate for each project while still grouping the projects together(not aggregate grouping, just one under the other).
Any help is greatly appreciated! :)
something like this? SQL FIDDLE to play with
SELECT project, resource, startdate
FROM testing
ORDER BY project, STR_TO_DATE(StartDate, '%d/%m')
basically your table is storing dates as a string and in order for you to order it you need to convert the strings to recognized dates... so the STR_TO_DATE() is a method to do that :)
You need to calculate the date used for the ordering:
select t.*
from table t join
(select project, min(startdate) as minsd
from table t
group by project
) tp
on t.project = tp.project
order by tp.minsd, t.project;
Note: this assumes that startdate is really stored as a date and not a string. If it is stored as a string, then you should convert it to a date first.
Can anyone help me to sort this out pleaase. i have a episode table and for an episode there will be following appointments . Episode table will be like
+-------------+------------+------------+------------+----------------+------+
| Episode_id | Patientid | St_date | End_date | Status | ... |
+-------------+------------+------------+------------+----------------+------+
| 61112345 | 100001 | 12-01-2010 | | Active | |
| 61112346 | xxxxxx | 20-01-2010 | 10-10-2011 | Withdrawn | |
| ......... | xxxxxxxx | 30-01-2010 | 10-05-2011 | Lost to follow | |
| ......... | xxxxxxxx | 01-02-2011 | Active | Active | |
+-------------+------------+------------+------------+----------------+------+
Status field holds the status of each episode.A episode has 6 appointments , 3 months per appointment. so totally an episode has 18 months . some patient may complete all 6 appointment , some may withdraw in the middle, or some will be lost to follow up. i need to create a dashboard .
Appointment table will have fields for
Appointment_id
PatientId
...
Stats // Completed or pending, which is used for reporting
For example if a patient complete 2 appointment and if he is marked as Withdrawn on episdode which means that he has withdrawn from 3rd visit and active for 2 visits, if we lost to follow him on 5th app, then he will be active for 4app and then he will be added to lost to follow up on 5th visit. if he completes all then he will added to active for all 6 visits. and the report should be like
Report from 01-01-2010 to 31-12-2010
+--------+--------+-------------+----------------+---------+
| | Active | Withdrawn | Lost to follow | Revised |
+------- +--------+-------------+----------------+---------+
| visit1 | 1500 | 30 | 5 | 5 |
| Visit2 | 1800 | 20 | 4 | 3 |
| Visit3 | 1900 | 45 | 3 | 2 |
| Visit4 | 1800 | 34 | 0 | 1 |
| Visit5 | 1900 | 30 | 0 | 1 |
| Visit6 | 1200 | 20 | 0 | 5 |
+--------+--------+-------------+----------------+---------+
Currently we are fetching the query and using loop only we are generating reports like this, but it is taking time to process, is there any way i can achieve using query itself.
It isn't really clear what you want to group by, but I can give you a general answer. After your where clause you can add "group by fieldname order by fieldname" where fieldname is the element you want to count or sum. You can then count(fieldname) or sum(fieldname) to either add or count.
This may be helpful: http://www.artfulsoftware.com/infotree/qrytip.php?id=105
Suppose I have two tables in the same MySQL DB:
The first is the inbound_campaign_visit table. It looks like this.
+----+-----------+------------------+---------------------+
| id | user_id | inbound_campaign | date |
+----+-----------+------------------+---------------------+
| 1 | 1 | 1 | 2013-02-18 13:00:00 |
| 2 | 1 | 2 | 2013-02-24 13:00:00 |
| 3 | 2 | 3 | 2013-01-01 01:00:00 |
| 4 | 2 | 2 | 2013-02-24 19:00:00 |
+----+-----------+------------------+---------------------+
A row on this table is generated every time a user visits my site as a result of clicking on a promotional campaign. The "date" column represents the time when they came to the site.
The second table is my transaction table.
+--------+---------+---------------------+
| id | user_id | creation_date |
+--------+---------+---------------------+
| 321639 | 1 | 2013-02-18 14:00:00 |
| 321640 | 1 | 2013-02-24 15:00:00 |
| 321641 | 1 | 2013-02-25 13:00:00 |
| 321642 | 1 | 2013-04-05 12:00:00 |
| 321643 | 2 | 2013-01-01 12:00:00 |
| 321644 | 2 | 2013-02-23 12:00:00 |
+--------+---------+---------------------+
A row on this table is created whenever a transaction happens. The "creation_date" column represents the time the transaction occured.
I want to create a report that will count the number of transactions per inbound campaign. The following rules must apply:
A transaction is considered related to an inbound campaign if the user_id values match that of the transaction and the transaction occurred within 30 days of an inbound_campaign_visit row being created.
A transaction can only apply to the most recent inbound campaign_visit for the given user.
The result table should look something like this:
+------------------+-------------------+
| inbound_campaign | transaction_count |
+------------------+-------------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
+------------------+-------------------+
Notice that transactions 321644 and 321642 are not counted as they fail rule 1. Also notice how transaction 321641 only applies to inbound_campaign 2 and not inbound_campaign 1 (even though both campaigns fall within the 30 day restriction defined in rule 1).
I have been struggling with this for some time so any help would be appreciated. Of course I could do this in code but there must be a way to do this in SQL. TIA.
SELECT a.inbound_campaign,
COUNT(b.user_ID) TotalCount
FROM inbound_campaign_visit a
LEFT JOIN transaction b
ON a.user_ID = b.user_ID AND
DATEDIFF(CURDATE(), b.creation_date) > 30
GROUP BY a.inbound_campaign
SQLFiddle Demo
I've got a excel sheet that contains all the employees that have worked for my company and is still working for us. It's a sheet of around 200 rows. Each row has basic info, like surname, name, position, qualification etc etc. 16 columns of basic info. Now, the tricky part is this. After the 16 columns, there are months (May-05 up to the present (Apr-12)). Under every month column, an employee either get's a 0 (contract), 1 (permanent), 2 (contract-terminated) or 3 (student).
What would be the best way to do this? I was thinking of 4 tables (listed below), where the one table determines permanently terminated people (for the sake of knowing who was on what type of employment).
MySQL Table: hr_employees
|-----------------|-------|----|----|----|
| employee_number | name | sur| etc| etc|
|-----------------|-------|----|----|----|
| 1 | Dave | F | xx | xx |
|-----------------|-------|----|----|----|
MySQL Table: hr_month
|----|--------|
| id | month |
|----|--------|
| 1 | May-05 |
| 2 | Jun-05 |
|----|--------|
MySQL Table: hr_status
|----|------|------|--------|
| id | e_no | date | status |
|----|------|------|--------|
| 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 1 |
|----|------|------|--------|
MySQL Table: hr_terminated
|----|------|
| id | e_no |
|----|------|
| 1 | 1 |
| 2 | 1 |
|----|------|
I hope you guys understand what I want to achieve, otherwise, ask a question, and I'll answer as best I can! :)
Thanks.
Here is a design that simplifies your data entry and is more relational database like and less Excel like, insofar as it's normalized.
MySQL Table: hr_employee
|-----------------|-------|----|----|----|
| employee_number | name | sur| etc| etc|
|-----------------|-------|----|----|----|
| 1 | Dave | F | xx | xx |
|-----------------|-------|----|----|----|
| 2 | Bob | M | xx | xx |
|-----------------|-------|----|----|----|
MySQL Table: hr_employee_status
|-----------------|------------|------------|--------|
| employee_number | from_date | to_date | status |
|-----------------|------------|------------|--------|
| 1 | 2005-05-01 | 2005-08-31 | 3 |
|-----------------|------------|------------|--------|
| 1 | 2006-05-01 | 2010-02-28 | 0 |
|-----------------|------------|------------|--------|
| 2 | 2010-03-01 | 9999-12-31 | 1 |
|-----------------|------------|------------|--------|
Here you can see that Dave was hired on as a student from May '05 to August '05, then he came back in May '06 as a contract employee which he worked as until the end of February '10. Then on March 1, 2010 Bob was hired as permanent employee and he is still working (max collating date means "until further notice").
The great advantage of this design is that you only have to enter/edit data when something changes, not once a month for every employee that you have or have ever had. You can also see what your workforce looked like at any given date (not just by months!) with a very simple SQL query.