what should be the query for creting logical view in Mysql? - mysql

i have to write one query in mysql .following is my table of ad_display
ad_displaysId | adv_id | campaign_id | adtypeId | clicked(boolean)
i have another table name as advertise which have ad_id
ad_id | advertisename
cammpaignId is in this table name as camp_table
campaign_id | camp_name
adtypeId is in this table name as adtype
adtypeId | adtype_name
now what i want is to create one view which gives me result like this from my ad_display Table
advertise_name | camp_name | adtype_name | count_of_clicked | count_of_row
here
count_of_clicked = count of row where adv_id=? campaignId=? adtypeId=? clicked=true
count_of_row= count of row where adv_id=? campaignId=? adtypeId=?
the additional inforamtion i can give is...that in ad_display there is multiple entry with same adv_id same camp_id same ad_typeId with clicked collumn is true or false.
i am totaly new in mysql..so can anyone suggest me query to do this with mysql?

Try this:
create view my_ad_view as
select
advertise_name,
camp_name,
adtype_name,
sum(clicked) as count_of_clicked,
count(*) as count_of_row
from ad_display ad
left join advertise a on a.ad_id = ad.ad_displaysId
left join camp_table ct on ct.campaign_id = ad.campaign_id
left join adtype at on at.adtypeId = ad.adtypeId
group by advertise_name, camp_name, adtype_name
Note the nice "trick" of sum(clicked), which works because in mysql true is 1 and false is 0, so summing a boolean counts how many times it is true.

Related

How to UPDATE a field from a SELECT table using JOIN

I have three tables.
inspectionreport
+----------+-----------------+------+
| ReportID | InspectionID_id | Date |
+----------+-----------------+------+
inspectionreport has ReportID PK, InspectionID_id FK, and date field Date.
inspection
+--------------+------------+
| InspectionID | PartID_id |
+--------------+------------+
inspection has InspectionID PK and PartID_id FK.
part
+--------+---------------+
| partID | LastInspected |
+--------+---------------+
part has a partID PK and date field LastInspected which is null by default.
What I want to do is fill LastInspected with THE LATEST Date for the relevant part.
So far I've tried using this SELECT query:
SELECT *
FROM moorings_inspectionreport
JOIN moorings_inspection
ON moorings_inspectionreport.InspectionID_id = moorings_inspection.InspectionID;
I figured I could use this to check if PartID_id matched partID as it's now only two tables. But I'm so confused as to how to pull this off as I'm quite unfamiliar with sql queries.
I also want to put this update into a daily running event that updates for every entry in the part table. So for me that adds a whole other level of confusion.
By joining the 2 tables inspection and inspectionreport and grouping by partid you can get the last lastinspected for each partid.
Then join to part and update:
update part p
inner join (
select i.partid, max(r.date) date
from inspection i
inner join inspectionreport r on r.inspectionid = i.inspectionid
group by i.partid
) t on p.partid = t.partid
set p.lastinspected = t.date

SUM() over a many-to-many relation in MYSQL

I have tables stanje and transakcija in a many-to-many relation, as shown in the image:
I need a MYSQL clause that returns all rows in stanje joined by a SUM() of every transakcija.iznos connected to a given stanje .
So far I have tried
select SUM(t.iznos)
from transakcija t
where transakcija_id in
(select transakcija_id from stanje_transakcija where stanje_id = ?)
which returns the SUM() correctly when given a stanje_id, but have no idea how to proceed, since I need sums for all rows in stanje.
Edit: added example output
------------------------------------
| stanje_id | naziv | SUM(t.iznos) |
------------------------------------
| 1 | a | 125.2 |
| 2 | b | -42.2 |
------------------------------------
If I understand correctly, you need to use JOIN in thoes tables by transakcija_id column and stanje_id column.
From your expect result you can try to use SUM with GROUP BY
select t2.stanje_id,t2.naziv,SUM(t.iznos)
from transakcija t
INNER JOIN stanje_transakcija t1 on t.transakcija_id = t1.transakcija_id
INNER JOIN stanje t2 on t2.stanje_id = t1.stanje_id
GROUP BY t2.stanje_id,t2.naziv

mysql using limit in a left join not working properly

I have two tables looking like this
Patient (table 1)
id | name
------------
1 | robel
2 | dave
Patient_followup (table 2)
id | Patient_id | date_created
-----------------------
1 | ---- 1 -- | 01/01/2015
2 | -----1 -- | 01/07/2016
I want to display all the patients with their perspective latest followup data. so i tried using this query
Select * from patient
left join Patient_followup pf on pf.Patient_id = patient.id
order by pf.date_created
Limit 1
but this is giving me only the first patient robel. i tryed removing the limit and its giving me two records of robel and one record of dave because robel has two followup data. so what should i do to get only one record of each patient ?
Try this:
Select
*
from
patient
left join
(SELECT
id as pf_id,
MAX(date_created) as latest_followup_date,
Patient_id
FROM
Patient_followup
GROUP BY
Patient_id) as pf
ON pf.Patient_id = patient.id
As mentioned by anton in the first comment, you need to use aggregation to get one record per patient.
Select patient.*,MAX(pf.date_created) as followupdate,group_concat(pf.date_created) from patient
left join Patient_followup pf on pf.Patient_id = p.patient.id
group by patient.id
order by pf.date_created
Here, you will get your values comma separated.
1) "Limit 1" will only return the first result. Typically this is used if the query will result in a very large result set and you only want the first few results.
Ex:
"LIMIT 30" will show the first 30 rows of the query.
2) I would change to setup of the tables so the query is smoother. Right now, you create a new line for each follow-up date even if the patient is already created. You could add another column in the table named "FollowUpDate". That way each patient record has the table id, patient id, creation date and followup date in the same row. That way, each patient has only one row.
EX:
Patient (table 1)
id | name | created_date | next_followup_date |
1 | Robel | 01/01/2015 | 01/01/2016 |
2 | Dave |[created_date]| [next_follup_date] |
Patient_followup (table 2)
id | Patient_id | date_created | followUpDate |
1 | 1 | 01/01/2015 | 06/01/2016 | // example date
2 | 1 | 01/01/2015 | 01/01/2016 |
3 | 2 |[date created]| [FollowUpDate] |
3) Change query to:
Use this select statement to get all patient records.
Select * from patient
left join Patient_followup pf on pf.Patient_id = patient.id
order by pf.Patient_id
Use this select statement to get the specific patient record information.
Select * from patient
inner join Patient_followup pf on pf.Patient_id = patient.id
where patient.id = 1 //to get robel. Edit this line as necessary, perhaps by user input...
order by pf.followUpDate
NOTE: When you insert a new record in Patient_followup, make sure you update Patient.next_followup_date.
I hope this helps!

How can I use JOIN in order to retrieve rows according to WHERE statements in distinct tables?

I got a database which controls some orders, each order has many items, naturally, an order is submitted by a user which belongs to a department.
Each user belongs to certain role, so orders are reviewed consecutively by distinct users with distinct higher roles. I control the next user who should do something with the order with a delegate field.
I will describe some of my tables with its relevant fields:
Department:
- id
- name
User:
- id
- name
- department_id
- role
Order:
- id
- user_id
- delegate // Here I got an enum for the multiple roles a user can get
Revision:
- id
- order_id
- user_id
- operation
Query
So what I need is a query for retrieving all orders whose users belong to a given department_id and the delegate field equals one provided argument OR where there are records at revisions table with user_id equal to another provided argument
What I got ...
With the aid of Eloquent ORM I got this style of query for first part of my needed result:
select `orders`.*, `users`.`department_id` from `orders` inner join `users` on `users`.`id` = `orders`.`user_id` where `users`.`department_id` = '1' and `delegate` = 'GERENTE DE DEPARTAMENTO' limit 2 offset 0
In order to include the OR where there are records at revisions table with user_id equal to another provided argument part of the query I tried to append to the query:
JOIN orders on revisions WHERE user_id = 5
But didn't work ...
The whole query I tried was:
select `orders`.*, `users`.`department_id` from `orders` inner join `users` on `users`.`id` = `orders`.`user_id` where `users`.`department_id` = '1' and `delegate` = 'GERENTE DE DEPARTAMENTO' JOIN orders on revisions WHERE user_id = 5
Example
I'm using hardcoded arguments in my queries examples as they are from a real example ... In that case I need to get only the whole orders whose users belong to deparment_id 1, delegate is 'GERENTE DE DEPARTAMENTO' OR if there are rows at revisions table which got the user_id set to 5
Orders:
+----+---------+-------------------------+
| id | user_id | delegate |
+----+---------+-------------------------+
| 1 | 4 | GERENTE DE DEPARTAMENTO |
| 2 | 2 | SUPERVISOR DE COMPRAS |
+----+---------+-------------------------+
Revisions:
+----+---------+----------+
| id | user_id | order_id |
+----+---------+----------+
| 1 | 5 | 2 |
| 2 | 5 | 2 |
+----+---------+----------+
A working query should take orders 1 and 2 only. How can I accomplish it? I'm interested about the MySQL needed and is a PLUS if it's Eloquent based query.
If I get you right, ie. you need:
orders that delegate= $delegate AND have user_id= x if that user got as department_id= $department_id at users, OR revisions by user with id = $userId
then this is the Eloquent way:
Order::where('delegate', $delegate)
->whereHas('user', function ($q) use ($depId) {
$q->where('department_id', $depId);
})->orWhereHas('revisions', function ($q) use ($userId) {
$q->where('user_id', $userId);
})
->get();
You could use left joins.
Your query might look something like this:
select distinct `orders`.*, `users`.`department_id` from `orders`
left join `users` on `order`.`user_id`=`users`.`id`
left join `revisions` on `order`.`id`=`revisions`.`order_id`
and `revisions`.`user_id`=?
where `users`.`department_id`=?
and (`order`.`delegate`=? or `revisions`.`id` is not null)

select statement with only rows which have set true in second table

i have two tables
activity
id | user_id | time | activity_id
1 | 1 | | 3
2 | 1 | | 1
and preferences
user_id | running | cycling | driving
1 | TRUE | FALSE | FALSE
i need result set of
id | user_id | time |
2 | 1 | |
i only need rows from first table whose values are set true in preferences table.
e.g activity_id for running is 1 which is set true in preferences table, so it returns while others doesn't.
If you can edit the schema, it would be better like this:
activity
id | name
1 | running
2 | cycling
3 | driving
user_activity
id | user_id | time | activity_id
1 | 1 | | 3
2 | 1 | | 1
preferences
user_id | activity_id
1 | 1
A row in preferences indicates a TRUE value from your schema. No row indicates a FALSE.
Then your query would simply be:
SELECT ua.id, ua.user_id, ua.time
FROM user_activity ua
JOIN preferences p ON ua.user_id = p.user_id
AND ua.activity_id = p.activity_id
If you want to see the activity name in the results:
SELECT ua.id, ua.user_id, ua.time, activity.name
FROM user_activity ua
JOIN preferences p ON ua.user_id = p.user_id
AND ua.activity_id = p.activity_id
JOIN activity ON ua.activity_id = activity.id
What I would probably do is join the tables on a common column, looks like user_id is a common column in this case, which gives access to the columns in both tables to query against in the where clause of the query.
Which type of join depends on what information you want from preferences
Handy Visual Guide for joins
So you could query
SELECT * FROM activity LEFT JOIN preferences ON activity.user_id = preferences.user_id WHERE preferences.columnIWantToBeTrue = true
I'm using left join since you mentioned you want the values from the first table based on the second table.
Mike B has the right answer. The relational model relates rows together by common values.
You've got a table named activity with an id column which looks like the primary key. The column name activity_id would typically be the name of a column in another table that is a foreign key to the activity table, referencing activity.id.
It looks like you've used the activity_id column in the activity table as a reference to either "running", "cycling" or "driving".
It's possible to match activity.activity_id = 1 with "running", but this is a bizarre design.
Here's an example query:
SELECT a.id
, a.user_id
, a.time
FROM activity a
JOIN preferences p
ON p.user_id = a.user_id
AND ( ( p.running = 'TRUE' AND a.activity_id = 1 )
OR ( p.cycling = 'TRUE' AND a.activity_id = 2 )
OR ( p.driving = 'TRUE' AND a.activity_id = 3 )
)
But, again, this is a bizarre design.
As a start, each table in your database should have rows that represent either an entity (a person, place, thing, concept or event that can be uniquely identified, is important, and we need to store information about), or a relationship between the entities.
From the limited information we have about your use case, the entities appear to be "user", an "activity_type" (running, cycling, driving), an "activity" (an amount of time, for a user and an activity_type) and some user "preference" about which activity_types the user prefers.
See the answer from Mark B for a possible schema design.