I have a database that has tables:
Click Internal - product clicks tracked by our system
Click External - product clicks tracked by a partner system. Number of clicks: click_internal >= click_external, also for each external click there is a column with bool click_external.click_valid
Conversion - purchases that happened after a click was tracked in partner system
Product - information about product that was clicked or bought
Producer - information about producer of the product
The database schema looks like this:
I would like to show number of valid external clicks and conversions for each producer for given date. So the result should look something like this:
So far I got:
SELECT
producer.name,
COUNT(click_external.id),
COUNT(conversion.id),
SUM(conversion.price)
FROM click_external
LEFT JOIN click_internal ON click_internal.id = click_external.click_internal_id
LEFT JOIN product ON product.id = click_internal.product_id
LEFT JOIN producer ON producer.id = product.producer_id
LEFT JOIN conversion ON click_internal.id = conversion.click_internal_id
WHERE click_external.click_valid = 1
AND click_external.date = "2017-02-09"
GROUP BY producer.id
-- GROUP BY click_external.id
The problem is when I try to group by producer.id the sum of COUNT(CLICK_EXTERNAL.id) column is greater than there are actually rows (clicks) in the DB. i.e. Sum of clicks by each provider is greater than number of ungrouped clicks.
I have also tried to group by click_external.id (as seen in the code comment) to see which rows are there. The number of rows in result is ok, but some rows are counted more times. i.e. COUNT(CLICK_EXTERNAL.id) column is greater than 1 at some rows.
What should I change in the SQL?
Related
I'm doing a left join on a table to get the number of leads we've generated today and how many times we've called those leads. I figured a left join would be the best thing to do, so I wrote the following query:
SELECT
COUNT(rad.phone_number) as lead_number, rals.lead_source_name as source, COUNT(racl.phone_number) as calls, SUM(case when racl.contacted = 1 then 1 else 0 end) as contacted
FROM reporting_app_data rad
LEFT JOIN reporting_app_call_logs racl ON rad.phone_number = racl.phone_number, reporting_app_lead_sources rals
WHERE DATE(rad.created_at) = CURDATE() AND rals.list_id = rad.lead_source
GROUP BY rad.lead_source;
But the problem with that, is that if in the reporting_app_call_logs table, there are multiple entries for the same phone number (so a phone number has been called multiple times that day), the lead_number (which I want to count how many leads were generated on the current day grouped by lead_source) equals how many calls there are. So the count from the LEFT table equals the count from the RIGHT table.
How do I write a SQL query that gets the number of leads and the total number of calls per lead source?
Try COUNT(DISTINCT expression)
In other words, change COUNT(rad.phone_number) to COUNT(DISTINCT rad.phone_number)
Im breaking my head with this little query so hopefully someone can tell me what is wrong with it. I need to group orders by same month and year as well as order status. So I have different table with which matches a number let's say 4 to an order status in text (let's say DELIVERED). I am trying get mySQL to tell me out of each Month/Year how many orders it had in every given status (even if that number is zero). Up to this point I receive the right answer except for the months/year that have zero occurences. So I only see for example: 05/205 | DELIVERED | 45, but if there is for example zero "PENDING" orders for 05/25 I do not see 05/2015 | PENDING | 0 and that is what i'm looking for. Thanks a bunch guys
select order_statuses.status, order_statuses.status_text,
Month(str_to_date(orders.order_date, '%d/%c/%y')) as Good_Month,
Year(str_to_date(orders.order_date, '%d/%c/%y')) as Good_Year,
CONCAT(Month(str_to_date(orders.order_date, '%d/%c/%y')), "/",Year(str_to_date(orders.order_date, '%d/%c/%y'))) as The_Date
from order_statuses
left outer join orders
on order_statuses.`status` = orders.order_status
where orders.admin_comments like '%moveit.ca%'
group by Good_Year, Good_Month, order_statuses.`status`
I am trying to produce a query that will generate a list of absent students whenever a my code is typed. The problem I am running into is that the output list is displaying none of the names of the students that were in class. My goal is to only list students that are over 30 days according to their most recent recorded date of attendance. Students that are not over 30 days will not be shown at all. It seems pretty simple enough however I'm running into a block. Is there a Syntax or two that I am missing?
SELECT trim(concat(name.fname,' ' ,name.mname,' ',name.lname)) as student, name.noiid as stuID, sum(meeting.meefoiid) as NO_CLASS, squadlt.ltfname as Squad
FROM name
LEFT JOIN meeting ON name.foiid = meeting.meefoiid
LEFT JOIN squadlt ON name.squadlt = squadlt.ltid
WHERE meeting.meefoiid IS NULL
AND MEEDATE >= '2014-09-12'
AND name.city = 'RICHMOND'
GROUP BY student
ORDER BY name.squadlt, student;
I'm fairly new to php / mysql programming and I'm having a hard time figuring out the logic for a relational database that I'm trying to build. Here's the problem:
I have different leaders who will be in charge of a store anytime between 9am and 9pm.
A customer who has visited the store can rate their experience on a scale of 1 to 5.
I'm building a site that will allow me to store the shifts that a leader worked as seen below.
When I hit submit, the site would take the data leaderName:"George", shiftTimeArray: 11am, 1pm, 6pm (from the example in the picture) and the shiftDate and send them to an SQL database.
Later, I want to be able to get the average score for a person by sending a query to mysql, retrieving all of the scores that that leader received and averaging them together. I know the code to build the forms and to perform the search. However, I'm having a hard time coming up with the logic for the tables that will relate the data. Currently, I have a mysql table called responses that contains the following fields,
leader_id
shift_date // contains the date that the leader worked
shift_time // contains the time that the leader worked
visit_date // contains the date that the survey/score was given
visit_time // contains the time that the survey/score was given
score // contains the actual score of the survey (1-5)
I enter the shifts that the leader works at the beginning of the week and then enter the survey scores in as they come in during the week.
So Here's the Question: What mysql tables and fields should I create to relate this data so that I can query a leader's name and get the average score from all of their surveys?
You want tables like:
Leader (leader_id, name, etc)
Shift (leader_id, shift_date, shift_time)
SurveyResult (visit_date, visit_time, score)
Note: omitted the surrogate primary keys for Shift and SurveyResult that I would probably include.
To query you join shifts and surveys group on leader and taking the average then jon that back to leader for a name.
The query might be something like (but I haven;t actually built it in MySQL to verify syntax)
SELECT name
,AverageScore
FROM Leader a
INNER JOIN (
SELECT leader_id
, AVG(score) AverageScore
FROM Shift
INNER JOIN
SurveyResult ON shift_date = visit_date
AND shift_time = visit_time --depends on how you are recording time what this really needs to be
GROUP BY leader ID
) b ON a.leader_id = b.leader_id
I would do the following structure:
leaders
id
name
leaders_timetabke (can be multiple per leader)
id,
leader_id
shift_datetime (I assume it stores date and hour here, minutes and seconds are always 0
survey_scores
id,
visit_datetime
score
SELECT l.id, l.name, AVG(s.score) FROM leaders l
INNER JOIN leaders_timetable lt ON lt.leader_id = l.id
INNER JOIN survey_scores s ON lt.shift_datetime=DATE_FORMAT('Y-m-d H:00:00', s.visit_datetime)
GROUP BY l.id
DATE_FORMAT here helps to cut hours and minutes from visit_datetime so that it could be matched against shift_datetime. This is MYSQL function, so if you use something else you'll need to use different function
Say you have a 'leader' who has 5 survey rows with scores 1, 2, 3, 4 and 5.
if you select all surveys from this leader, sum the survey scores and divide them by 5 (the total amount of surveys that this leader has). You will have the average, in this case 3.
(1 + 2 + 3 + 4 + 5) / 5 = 3
You wouldn't need to create any more tables or fields, you have what you need.
I have a custom shop, and I need to redo the shipping. However, that is sometimes later, and in the meantime, I need to add a shipping option for when a cart only contains a certain range of products.
SO there is a ship_method table
id menuname name zone maxweight
1 UK Standard ukfirst 1 2000
2 UK Economy uksecond 1 750
3 Worldwide Air world_air 4 2000
To this I have added another column prod_restrict which is 0 for the existing ones, and 1 for the restricted ones, and a new table called ship_prod_restrict which contains two columns, ship_method_id and item_id, listing what products are allowed in a shipping category.
So all I need to do is look in my transactions, and for each cart, just check which shipping methods are either prod_restrict of 0 or have 1 and have no products in the cart that aren't in the restriction table.
Unfortunately it seems that because you can't values from an outer query to an inner one, I can't find a neat way of doing it. (edited to show the full query due to comments below)
select ship_method.* from ship_method, ship_prod_restrict where
ship_method.`zone` = 1 and prod_restrict='0' or
(
prod_restrict='1'
and ship_method.id = ship_prod_restrict.ship_method_id
and (
select count(*) from (
select transactions.item from transactions
LEFT JOIN ship_prod_restrict
on ship_prod_restrict.item_id = transactions.item
and ship_prod_restrict.ship_method_id=XXXXX
where transactions.session='shoppingcartsessionid'
and item_id is null
) as non_permitted_items < 1 )
group by ship_method.id
gives you a list of whether the section matches or not, and works as an inner query but I can't get that ship_method_id in there (at XXXXX).
Is there a simple way of doing this, or am I going about it the wrong way? I can't currently change the primary shipping table, as this is already in place for now, but the other bits can change. I could also do it within PHP but you know, that seems like cheating!
Not sure how the count is important, but this might be a bit lighter - hard to tell without a full table schema dump:
SELECT COUNT(t.item) FROM transactions t
INNER JOIN ship_prod_restrict r
ON r.item_id = t.item
WHERE t.session = 'foo'
AND r.ship_method_id IN (**restricted, id's, here**)