Count if a user has reached the borrwing limit - mysql

I've setup a fiddle with tables and data here
I'm trying to write a single sql to check if user has reached the borrowing limit for each category.
Right now, it's done using severals sql statements called after each other.
But the way it goes is simple.
memId and id come through a querystring.
$medId = $_POST['memId']; Using 1 for this example. This is the members Id.
$id = $_POST['id']; Using 4 for this example. This is the item being lent.
After that I do:
select id, holder from collection_db where id = 4 // We have a valid item
select borrowMax from collection_db where id = (holder from the previous select) and category = 10 //Result = 2. Category indicates its a label and not a borrowable item.
select count(borrowedId) from lendings where memId = 1 and holder = (holder from the 1st query) //He's borrowed 2, under 1, so cant borrow any more. User 2 may borrow however.
if (count => borrowMax) {echo 'Cannot borrow more.';} else {echo 'Added to'}
How can this be combined into a single sql or is it best left this way?

This seems to produce a correct result set:
SELECT col1.id, col1.holder, col2.borrowMax, count(lend.borrowedId) as `count`
FROM collection_db col1
INNER JOIN collection_db col2
ON col1.holder = col2.id
INNER JOIN lendings lend
ON col1.holder = lend.holder
WHERE col1.id = $id
AND col2.category = 10
AND lend.memId = $medId

I think this combines the queries:
select max(c.borrowMax) as BorrowMax, COUNT(*)
from collection_db c join
collection_db c1
on c.id = c1.holder and c1.id = 4 and c.category = 10 join
lendings l
on l.holder = c1.holder;
It does make an assumption that the join between c and c1 does not produce duplicate rows. But you have this requirement by using = in the original query (rather than join).

Related

SQL Left Join Query to match all restriction from result

I´m trying to filter data with some categories where i get a result matching all given slug / type parameteres.
Currently i got stuck with extendending my current query to get the data with a single query. My current query looks like that:
SELECT t.slug, tc.t_id, tc.c_id
FROM tc
LEFT JOIN t ON t.id = tc.t_id
WHERE
(t.type = 'offerAges' AND t.slug = '14-16')
OR
(t.type = 'offerSportTypes' AND t.slug = 'football')
Gives me following result:
# slug t_id c_id
1 football 13 40
2 14-16 28 39
3 14-16 28 40
The result i want is that i just get the results where t_id AND c_id are matching. For example in my table the items 1 & 3.
Fiddle: https://www.db-fiddle.com/f/vQUU9C9iXj4gotE7YGDq6W/1
You can use aggregation. In this case:
SELECT tc.c_id
FROM tc JOIN
t
ON t.id = tc.t_id
WHERE (t.type = 'offerAges' AND t.slug = '14-16') OR
(t.type = 'offerSportTypes' AND t.slug = 'football')
GROUP BY tc.c_id
HAVING COUNT(DISTINCT t.type) = 2;
If you want the slugs, I would recommend using GROUP_CONCAT() to put them in a single column:
GROUP_CONCAT(t.slug)

Disacrding multiple duplicate records from a left join

I have two tables:-
gallery
gallery_favorite
The user_id in gallery table means the user who posted the item. The user_id in gallery_favorite means the user who added the item in his favorite list. If favorite = 0, then it means the user had initially added the item in favorite list but later removed it.
Now, I want to fetch all the gallery items along with its favorite status. Here is my query:-
Select distinct `gallery`.`id`, `gallery`.`caption`, `gallery`.`type`,
`gallery`.`video`, `gallery`.`image`, `gallery`.`type`,
`gallery`.`created_date`, `gallery`.`modified_date`,
`gallery_favorite`.`favorite`, `gallery`.`user_id`
from `gallery`
left join `gallery_favorite` on `gallery_favorite`.`gallery_id` = `gallery`.`id`
where
(`gallery`.`type` = 'i'
and `gallery`.`status` = 1
and `gallery`.`deleted` = 0)
and
((`gallery`.`user_id` != 11 and `gallery`.`private` = 0)
or `gallery`.`user_id` = 11)
limit 20 offset 0
But a syou can see, I am getting duplicate records depending upon the number of rows wrt to a gallery item in the gallery favorite table. How can I modify the query to get only one record (along with my own favorite status)?
I guess you are getting duplicate records because you have not joined both the table on user_id -
Try below query -
Select distinct `gallery`.`id`, `gallery`.`caption`, `gallery`.`type`,
`gallery`.`video`, `gallery`.`image`, `gallery`.`type`,
`gallery`.`created_date`, `gallery`.`modified_date`,
`gallery_favorite`.`favorite`, `gallery`.`user_id`
from `gallery`
left join `gallery_favorite` on `gallery_favorite`.`gallery_id` = `gallery`.`id`
and `gallery_favorite`.`user_id` = `gallery`.`user_id`
where
(`gallery`.`type` = 'i'
and `gallery`.`status` = 1
and `gallery`.`deleted` = 0)
and
((`gallery`.`user_id` != 11 and `gallery`.`private` = 0)
or `gallery`.`user_id` = 11)
limit 20 offset 0
Assuming the gallery as many favorites from different users. It makes no sense to display exclusively a hit favorite to a user and gallery alone. Counting them makes sense.
Select `gallery`.`id`, `gallery`.`caption`, `gallery`.`type`,
`gallery`.`video`, `gallery`.`image`, `gallery`.`type`,
`gallery`.`created_date`, `gallery`.`modified_date`,
sum(gallery_favorite`.`favorite`) as total_favorites -- count them group function aggregate
from `gallery`
left join `gallery_favorite` on `gallery_favorite`.`gallery_id` = `gallery`.`id`
where
(`gallery`.`type` = 'i'
and `gallery`.`status` = 1
and `gallery`.`deleted` = 0)
and
((`gallery`.`user_id` != 11 and `gallery`.`private` = 0)
or `gallery`.`user_id` = 11)
and gallery_favorite`.`favorite` = 1 -- count only the favorites
GROUP BY `gallery`.`id` -- GROUP CLAUSE
This is how a join works. You get all rows matching the condition. You can either group the result by the fields in the left table (thus eliminating duplicates in the output) or join with a table that has one entry per gallery item -- this requires joining with a (SELECT ... FROM gallery_favorite GROUP BY gallery_id)

sql multiple where on join

A have a table called advert_property
And I have a table advert, which is not important, advert properties connects to advert by advert_id column in advert_property table.
I wrote this SQL request :
SELECT *
FROM `advert`
JOIN advert_property ON advert.id = advert_property.advert_id
WHERE (advert_property.property_id = 1
AND advert_property.property_value = "Манчего")
AND (advert_property.property_id = 2
AND advert_property.property_value = "козий")
What I want to get, is advert that have certain properties, for example : I want an idvert that have property_id = 1 and property_value = "Манчего" AND have property_id = 2 and property_value = "козий". SQL request returns null, how should I change my SQL request. Thanks!
Assuming I'm understanding your question correctly and you want to return all adverts that have both properties, then there are a couple ways of doing this using multiple joins, exists, in, group by...
Here is the method using multiple joins:
SELECT a.*
FROM `advert` a
JOIN advert_property ap ON a.id=ap.advert_id
AND ap.property_id = 1 AND ap.property_value = 'Манчего'
JOIN advert_property ap2 ON a.id=ap2.advert_id
AND ap2.property_id = 2 AND ap2.property_value = 'козий'
You can't return all columns * where the property_id is both 1 and 2 because a record can't have two values for the same field. You can, however, return records where the property_id is 1 OR 2. You could then have it only return DISTINCT advert_id where this is true:
SELECT DISTINCT advert_id
FROM `advert` JOIN advert_property ON advert.id=advert_property.advert_id
WHERE (advert_property.property_id = 1 AND advert_property.property_value = "Манчего")
OR (advert_property.property_id = 2 AND advert_property.property_value = "козий")
Query which you are trying to execute will never give you a result because it is trying to get a row with property id = 1 and property id = 2
For same row, there will never be two property_ids (1,2).
You need to review your where conditions.
My be what you need in where condition is as below(Either id will be 1 or id will be 2):
Try this :
(advert_property.property_id = 1 AND advert_property.property_value = "Манчего")
OR
(advert_property.property_id = 2 AND advert_property.property_value = "козий")

query is not working correctly

I have these tables:
single_user_has_university_has_course
single_user_users_id_user university_has_course_university_id_university university_has_course_course_id_course first_year_school last_year_school grade
1 1 1 2000 2001 15
And
university_has_course
university_id_university course_id_course
1 1 <<< I want to select this
15 1
1 3
15 3
The problem is that the query below return all rows where course_id_course = 1 but ignore theuniversity_id_university = 1`. Then, will return two rows.
query:
SELECT A.first_year_school, A.last_year_school, A.grade, U.university, C.course, T.type_course
FROM single_user_has_university_has_course A
INNER JOIN university_has_course Q
ON A.university_has_course_course_id_course = Q.course_id_course
INNER JOIN university U
ON Q.university_id_university = U.id_university
INNER JOIN course C
ON Q.course_id_course = C.id_course
INNER JOIN type_course T
ON C.type_course_id_type_course = T.id_type_course
AND A.single_user_users_id_user = ?
You are joining the last table to the previous joins on 2 constraints C.type_course_id_type_course = T.id_type_course AND A.single_user_users_id_user = ?. I think you want to write it as a WHERE clause. So replace your last line with:
WHERE A.single_user_users_id_user = ?
But you're not also trying to filter university_id_university = 1, so you may want to add it to the WHERE clause as well:
WHERE A.single_user_users_id_user = ? AND Q.university_id_university = ?

Return 2 columns using subquerys in main query in mysql

I wish to populate a table on in a mysql database. Firstly I'd like to pull back all of the possibilities and them trim out the unrequired ones (easier than just adding them by hand).
The final table is:
combinations
combID
productID
type
content
exclude
extrafield2
extrafield6
The data comes from
extrafields_values
exvalueID
productID
extrafieldID
content
For each product I need to get return a row for each combination in extra_field_values (extrafieldID = 2 and extrafieldID = 6)
For instance:
productID = 700
extrafield2 = E, D, F
extrafield6 = 34,35,36,37
Returns the exvalueID to extrafields2 and 6 for each combination
So far I've tried:
SELECT EV.productID, extraFieldID, content AS extrafield6,
(SELECT content AS extrafield2
FROM wjf_extrafields_values AS EV2
INNER JOIN wjf_products AS P2
WHERE extraFieldID = 6) AS extrafield2
FROM wjf_extrafields_values AS EV
INNER JOIN wjf_products AS P ON P.productID = EV.productID
WHERE extrafieldID = 6
I believe you just need to link your wjf_products table to your extrafield_values table twice as shown below.
select p.productID, ev1.content as extrafield2, ev2.content as extrafield6
from wjf_products p inner join extrafields_values ev1 on p.productID = ev1.productID
inner join extrafields_values ev2 on p.productID = ev2.productID
where ev1.extraFieldID = 2
and ev2.extraFieldID = 6
Why not just create and use two views instead of a query.
View1 = Combinations
View2 = Subset of View1
Insert data using the View2