MYSQL PHP select the opposite of a query - php

I have two tables.
One table has everything I need including a cardId(PK)
The other name is a user type table. This table stores the userId and the cardId(FK).
SELECT ci.cardId, ci.year, ci.name, ci.number
FROM USERCARDS uc
INNER JOIN CARDINDEX ci ON uc.cardId = ci.cardId
WHERE uc.userId = 'USER_ID'
So for this query, it will display the cardId, year, name, and number from the CARDINDEX. It will only display the cards that the user has saved in USERCARDS.
I want to do the opposite. If a user is looking at, lets just say, 5 cards, but the CARDINDEX has 50 cards, this query will display the information for the five cards. However, for a new query, I would want to show the remaining 45 cards. Basically, they cant add a card they already are following.
I tried to have uc.cardId != ci.cardId but that didn't work. Im kind of lost.

You can phrase this as a LEFT JOIN:
SELECT ci.cardId, ci.year, ci.name, ci.number
FROM CARDINDEX ci LEFT JOIN
USERCARDS uc
ON uc.cardId = ci.cardId AND
uc.userId = 'USER_ID'
WHERE uc.cardID IS NULL;
Alternatively, you could write this using `NOT EXISTS:
SELECT ci.cardId, ci.year, ci.name, ci.number
FROM CARDINDEX ci
WHERE NOT EXISTS (SELECT 1
FROM USERCARDS uc
WHERE uc.cardId = ci.cardId AND
uc.userId = 'USER_ID'
);

Related

What join to use

I have two tables, one for registered users and one to store votes.
We are logging in with registrants.id and registrants.zipcode. Once they vote their votes are inserted into the votes table, along with their Registration ID.
Im trying to right a select statement that returns a record that will select all the records for Matched ID and Zipcode, but the ID is not in the Votes.voter column. i have tried all kinds of variations of all the joins i can think of. is it something simple i am missing.
SELECT * FROM registrants
LEFT JOIN votes on registrants.id = votes.voter
WHERE registrants.id = 1 AND registrants.zipcode = 46706 and votes.voter <> 1
Perhaps a not exists query:
select * from registrants
where registrants.zipcode = '46706'
and not exists (select 1 from votes where registrants.id = votes.voter)

Distinct Values from MySQLi Query

I am trying to only show unique userIds (userIds are (0,1,2,3,4,5,6,7,8,9 etc...) for the query I am running. I tried using DISTINCT in my query, but it only shows me unique values of the rows that have 2 or more of the same userId.
Is there a way I can use php to only show the unique values. My weak points are arrays and it makes it more complicated because its using data from a MySQLi query.
Example right now I have with the query now (lets say its GROUP BY rentPaid DESC and the rent total is 800.00 for all users):
userID rentPaid rentMonth
2--------800.00------April
1--------500.00------April
3--------400.00------April
3--------400.00------April
1--------200.00------April
1--------100.00------April
Example desired output:
userID rentPaid rentMonth
2--------800.00------April
1--------500.00------April
3--------400.00------April
Can I do this with MYSQL because I tried DISTINCT and it wouldn't work, how about PHP?
Query:
SELECT
properties.*,
leases.*,
users.userId, users.primaryPhone,
CONCAT(users.userFirstName,' ',users.userLastName) AS user,
admins.adminName, payments.*
FROM
properties
LEFT JOIN leases ON properties.propertyId = leases.propertyId
LEFT JOIN assigned ON properties.propertyId = assigned.propertyId
LEFT JOIN admins ON assigned.adminId = admins.adminId
LEFT JOIN users ON properties.propertyId = users.propertyId
LEFT JOIN payments ON properties.propertyId = payments.propertyId
WHERE
payments.rentMonth = '$currentMonth' AND
payments.rentYear = '$currentYear'
Edit: Please excuse my formatting, this is my first post.
Edit: Added query....its long, but works lol. I only want unique userIds (no double or triple userIds etc...)
I suspect this is what you want:
SELECT userID, MAX(rentPaid) AS maxRentPaid, rentMonth
FROM yourTable
WHERE rentMonth = "April"
GROUP BY userID
ORDER BY maxRentPaid

Mysql Complex Join Query Issue

I have 5 mysql tables as described below.
clinics table
id
name
d_location_subscription table
id
clinic_id
t_id //t_id will contain a foreign key of d_cities, d_states or d_countries table
type "country" "state" "city"
d_countries table
id
name
code
d_states table
id
d_country_id
name
code
d_city table
id
d_state_id
name
code
d_location_subscription table is used to record clinic's subscription for a location(it may be a city, state or country). I'm expecting to get all subscribed cities for a specific
clinic using d_location_subscription table.
For example, if clinic A is subscribed to Texas state, I should be able to get all city ids for clinic A.
I created following sql query, it looks ugly but generate a close result what i want to achieve.
select
`d`.`id` AS `clinic_id`,
if((`dct`.`id` is not null),`dct`.`id`,if((`dct1`.`id` is not null),`dct1`.`id`,`dct2`.`id`)) AS `d_city_id`
from ((((((((
`d_location_subscriptions` `dls`
join `clinics` `d`
on((`d`.`id` = `dls`.`clinic_id`)))
left join `d_countries` `dc`
on(((`dc`.`id` = `dls`.`t_id`) and (`dls`.`type` = 'country'))))
left join `d_states` `ds`
on((`ds`.`d_country_id` = `dc`.`id`)))
left join `d_cities` `dct2`
on((`dct2`.`d_state_id` = `ds`.`id`)))
left join `d_states` `ds1`
on(((`ds1`.`id` = `dls`.`t_id`) and (`dls`.`type` = 'state'))))
left join `d_cities` `dct`
on((`dct`.`d_state_id` = `ds1`.`id`)))
left join `d_cities` `dct1`
on(((`dct1`.`id` = `dls`.`t_id`) and (`dls`.`type` = 'city'))))
)
when there is record with type "country" in d_location_subscription table, I receive following result. total number of records returned are equal to the number of d_states table records.
How should I get rid of those Null values by changing above query?
And please advice me if this is the correct way to acheive similar functionality. Thanks in advance :)
The quickest, dirtiest way to achieve what you want is just to append this where condition to your query:
WHERE d_city_id is not null
but you might prefer to rework your query and decide where you really need LEFT joins and not INNER joins
the IF() computed column is in essence what STT LCU was trying to offer, but you can't use that directly in the where for some reason.
I've rewritten your query, but with different aliases to better follow the origination of the tables / relationships to get the data. In the end, I've added a where to test for ANY ONE of the "ID" values as NOT NULL. If they are ALL Null, the record should be excluded..
select
d.id AS clinic_id,
if(CityViaState.id is not null, CityViaState.id,
if( ByCity.id is not null, ByCity.id, CityViaCountry.id )) AS d_city_id
from
d_location_subscriptions dls
join clinics d
ON dls.clinic_id = d.id
left join d_countries ByCountry
ON dls.t_id = ByCountry.id
and dls.type = 'country'
left join d_states StateViaCountry
ON ByCountry.id = StateViaCountry.d_country_id
left join d_cities CityViaCountry
ON StateViaCountry.id = CityViaCountry.d_state_id
left join d_states ByState
ON dls.t_id = ByState.id
and dls.type = 'state'
left join d_cities CityViaState
ON ByState.id = CityViaState.d_state_id
left join d_cities ByCity
ON dls.t_id = ByCity.id
and dls.type = 'city'
where
CityViaState.id is not null
OR ByCity.id is not null
OR CityViaCountry.id is not null

Joining Multiple Rows From Within

The Problem
I have four tables I need to pull info from, two are just simple joins.
My query is returning nothing. Basically, there are forms I need to make sure I tied to my patient from one table, and the next table, to allow me to pull the form name so it's the correct form.
What I have
select person.first, person.last, treatmentPlan.created, treatmentPlan.updated, treatmentPlan.provider_id, intake.created, intake.updated, assesment.created, assesment.updated, discharge.created, discharge.updated
from form_patient_tie intake
LEFT OUTER JOIN form_patient_tie treatmentPlan ON intake.patient_id = treatmentPlan.patient_id
LEFT OUTER JOIN form_patient_tie assesment ON intake.patient_id = assesment.patient_id
LEFT OUTER JOIN form_patient_tie discharge ON intake.patient_id = discharge.patient_id
JOIN form as intakeForm ON intakeForm.form_id = intake.form_id
LEFT OUTER JOIN form treatmentPlanForm ON treatmentPlan.form_id = treatmentPlanForm.form_id
LEFT OUTER JOIN form assesmentForm on assesment.form_id = assesmentForm.form_id
LEFT OUTER JOIN form dischargeForm on discharge.form_id = dischargeForm.form_id
JOIN patient ON intake.patient_id = patient.patient_id
JOIN person on patient.person_id = person.person_id
WHERE (treatmentPlanForm.form_name LIKE "%Counseling Treatment Plan%" OR treatmentPlanForm.form_name IS NULL)
AND (intakeForm.form_name LIKE "%Counseling Intake%" OR intakeForm.form_name IS NULL)
AND (assesmentForm.form_name LIKE "%Counseling Assesment Review%" OR assesmentForm.form_name IS NULL)
AND (dischargeForm.form_name LIKE "%Counseling Discharge%" OR dischargeForm.form_name IS NULL)
It returns nothing even though I know there is a patient with Intake, Review, and Assessment done, but no discharge. If they have all 4, it works right, but if they are missing one, it doesn't.
It should look like
John Doe 2013-01-13 2013-01-15 2013-02-13 etc. It's definitely allowed for them to be null as not every person will have one filled out.
It looks to me as though your join to the "form" table (intakeForm alias) should also be a LEFT JOIN. Otherwise if there is not a match on the intake form, the entire query will return nothing.

SQL Advice - selecting multiple rows from a table as an innerJoin

I've been working on a project that until now has only needed to find 1 row from the joined table. But now I need to grab multiple rows..
So as it stand my sql works something like:
Select rows for each company for this particular project which alone would find company details (name, id, telephone.. blah).
Then I join a table that contains form data submitted for each company (multiple forms - so multiple records)
Until now i have been specifying one formid to look for in the join, but now i need to specify multiple ones.
If I use WHERE form_id = 1 OR form_id = 2 OR form_id = 3 ... I get a result of only the first form match that is found per company..
If I mix up the query so it looks for the forms 1st and returns multiple records for each company with different form data - that works in this sense..
But I am then looping through this array in a view and creating a table row per record (previously each row was a new company) but using the latter would cause multiple records to show for the same company.
Any way I can do this? I tried group by with the latter method but this results in only 1 record again.
SELECT DISTINCT p.project_company_has_user_id, p.project_company_has_user_project_id, p.project_company_has_user_user_id, c.company_id, c.company_hall_no, c.company_company_name, c.company_type, c.company_country, c.company_stand_number, c.company_image_file_1, p2.project_id, p2.project_name, u.user_id, u.user_username, o.orders_id, o2.order_detail_id, o2.order_detail_product_id, f2.form_question_has_answer_id, f2.form_question_has_answer_request, f2.form_question_has_answer_form_id, f2.form_question_has_answer_user_id
FROM project_company_has_user p
INNER JOIN company c ON p.project_company_has_user_company_id = c.company_id
INNER JOIN project p2 ON p.project_company_has_user_project_id = p2.project_id
INNER JOIN user u ON p.project_company_has_user_user_id = u.user_id
INNER JOIN form f ON p.project_company_has_user_project_id = f.form_project_id
LEFT JOIN orders o ON p.project_company_has_user_user_id = o.orders_user_id
LEFT JOIN order_detail o2 ON ((o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
LEFT JOIN form_question_has_answer f2 ON ((f2.form_question_has_answer_form_id = 297 AND f2.form_question_has_answer_user_id = p.project_company_has_user_user_id))
WHERE (f.form_template_name = "custom" AND p.project_company_has_user_garbage_collection = 0 AND p.project_company_has_user_project_id = 48) AND (LCASE(c.company_country) LIKE "%uk%" OR LCASE(c.company_country) LIKE "%uk%") ORDER BY company_company_name asc
you need another field in order_detail as o2 . this field is row_index(position),etc for positioning record
LEFT JOIN order_detail o2 ON (o2.row_index=1 AND (o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
Personally I would use an Outer Join for the table of which elements you need to list all matches. Should you them need to clean up that data you can build the logic into the Join Condition (as step 2). Depending on the volume of data you are handling and whether or not you need to reuse it later in the same proc, you may want to post that primary dataset into a temp table and use that as source (primary) for your later logic.
Hope that helps. If you need the code, let me know, but it is pretty straight forward.
Regards
Mac

Categories