SQL query between 2 tables - php

I have a database with 2 tables that I am working with (SugarCRM).
I am querying the table cases_audit to get a row count of cases with a status changed to closed. All this works great.
What I am having trouble with is figuring out how to take the id from cases_audit and ensure that under table cases that same id has a type = "support"
// Query cases_aduit to find out how many cases were closed -0 days ago
$query_date_1_closed = "select * from cases_audit where after_value_string = 'Closed' and date_created LIKE '$date_1 %'";
$rs_date_1_closed = mysql_query($query_date_1_closed);
$num_rows_1_closed = mysql_num_rows($rs_date_1_closed);

Assuming the column id in cases_audit referes to id in cases (which is not very likely), this query gives you every column from the audit plus type from the appropriate case:
SELECT
A.*, C.type
FROM cases_audit A
INNER JOIN cases C ON A.id=C.id
WHERE A.after_value_string = 'Closed' AND A.date_created LIKE '$date_1 %'
If you want to count the closed support cases, add C.type to your WHERE condition:
SELECT
COUNT(*)
FROM cases_audit A
INNER JOIN cases C ON A.id=C.id
WHERE A.after_value_string = 'Closed' AND A.date_created LIKE '$date_1 %' AND C.type = 'support'

cases_audit.parent_id is the field which relates to cases.id

Related

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

Join a query into another query with column computation

I have three tables named issue_details, nature_payments, and rci_records. Now I have this query which joins this three tables.
SELECT issue_details.issue_date AS Date,
issue_details.check_no AS Check_No,
payees.payee_name AS Name_payee,
nature_payments.nature_payment AS Nature_of_Payment,
issue_details.issue_amount AS Checks_issued,
issue_details.nca_balance AS Nca_balance
FROM
issue_details
INNER JOIN
nature_payments ON
issue_details.nature_id = nature_payments.nature_id
INNER JOIN
payees ON
issue_details.payee_id = payees.payee_id
ORDER BY Date Asc, Check_no ASC
On my column in Nca_balance, this is a computed differences of every issuances of check. But you may not know what really the process of how I got the difference but to make it simple, let's say that I have another query
that dynamically get also the difference of this nca_balance column. Here is the query:
SELECT r.*,
(#tot := #tot - issue_amount) as bank_balance
FROM (SELECT #tot := SUM(nca_amount) as nca_total FROM nca
WHERE account_type = 'DBP-TRUST' AND
year(issue_date) = year('2015-01-11') AND
month(issue_date) = month('2015-01-11')
)
vars CROSS JOIN issue_details r
WHERE r.account_type = 'DBP-TRUST' AND
r.issue_date = '2015-01-11'
ORDER BY r.issue_date, r.check_no
I know it you may not get my point but I just want to replace the first query of the line
issue_details.nca_balance AS Nca_balance
with my own computation on my second query.
Please help me combine those two query into a single query. Thanks

Faster Way to Code this MysQL Query using GROUP BY, HAVING, COUNT, ORDER BY and 2 Tables

I am trying to use this to query 2 tables and get results based on factors from mainly one table. I would prefer doing 1 query instead of 1 query with many sub queries in a while or foreach.
SELECT a.request, a.city
FROM pages a, TNDB_CSV2 b
WHERE a.main_id = b.PerformerID
AND b.PCatID = '3'
AND a.catnum = '303'
AND a.city = b.City
AND b.TicketsYN = 'Y'
AND b.CountryID IN ('38', '217')
GROUP BY b.PerformerID, b.City HAVING COUNT(*) > 4
ORDER BY a.name ASC
So basically what this is saying is that I want to get results in 'pages' where records in 'TNDB_CSV2' have at least 4 matches of 'PerformerID' and 'City'.
The query works correctly, the issue is that it takes between 55-67 seconds to run which is massively way too long. Similar queries should take a fraction of a second. I have never grouped by 2 columns using HAVING and COUNT before so I am thinking there might be a much more efficient way of doing this.
The query currently returns 1,011 records and I looked to make sure that the conditions match the results and they do.
Here is your query, formatted with a proper join clause:
SELECT a.request, a.city
FROM pages a join
TNDB_CSV2 b
on a.main_id = b.PerformerID and a.city = b.City
WHERE b.PCatID = '3' AND
b.TicketsYN = 'Y' AND
b.CountryID IN ('38', '217') and
a.catnum = '303'
GROUP BY b.PerformerID, b.City
HAVING COUNT(*) > 4
ORDER BY a.name ASC;
You should be able to improve the performance of this query with indexes. Here are two that I can think of:
pages(catnum, main_id, city, name)
TNDB_CSV2(PerformerID, city, PCatID, TicketsYN, CountryID);

Join tables with comma values

I have a hard nut to crack with joing 3 tables.
I have a newsletter_items, newsletter_fields and newsletter_mailgroups which I want to be joined to get a list of newsletters.
The newsletter_items contains the fields:
letter_id, letter_date, receivers, template, status
That can look like
1, 1234567899, 1,2 (comma separated), standard.html, 1
newsletter_fields contains the fields:
field_uid, field_name, field_content, field_letter_uid
That can look like
1, letter_headline, A great headline, 1
where field_letter_uid is the newsletter for which the field belongs to.
and newsletter_mailgroups contains the fields:
mailgroup_id, mailgroup_name, number_of_members
That can look like
1, Group1, 233
2, Group2, 124
3, Group3, 54
What I want is to combine these 3 tables to that I can get a list of all the newsletter like this:
Letter date | Letter headline | Receivers | Status
2008-01-01 12:00:00 | A great headline | Group1, Group 2 | 1
So in short I want my SQL query to join the 3 tables and in that process select the receivers from the mailgroup table and display them comma separated like Group1, Group 2
This what I got now
SELECT A.*, B.* FROM newsletter_items A, newsletter_fields B, WHERE B.field_letter_uid = A.letter_id AND field_name = 'letter_headline' AND A.template = '". $template ."';
But I can't seem to figure out how to get the mailgroups into that.
I recommend that you make your joins explicit.
It makes it easier to debug your query and to change inner with left joins.
There is absolutely never a good reason to use SQL '89 implicit join syntax.
SELECT ni.*
, nf.*
, group_concat(nm.mailgroup_name) as mailgroups
FROM newsletter_items ni
INNER JOIN newsletter_fields nf
ON (nf.field_letter_uid = ni.letter_id)
INNER JOIN newsletter_mailgroups nm
ON (find_in_set(nm.mailgroup_id, ni.receivers))
WHERE
nf.field_name = 'letter_headline'
ni.template = '". $template ."'
GROUP BY ni.letter_id;
Regarding your database design.
I recommend you normalize your database, that means that you move the comma separated fields into a different table.
So you make a table receivers
Receivers
----------
id integer auto_increment primary key
letter_id integer not null foreign key references newsletter_items(letter_id)
value integer not null
You then remove the field receiver from the table newsletter_items
Your query then changes into:
SELECT ni.*
, group_concat(r.value) as receivers
, nf.*
, group_concat(nm.mailgroup_name) as mailgroups
FROM newsletter_items ni
INNER JOIN newsletter_fields nf
ON (nf.field_letter_uid = ni.letter_id)
INNER JOIN newsletter_mailgroups nm
ON (find_in_set(nm.mailgroup_id, ni.receivers))
LEFT JOIN receiver r ON (r.letter_id = ni.letter_id)
WHERE
nf.field_name = 'letter_headline'
ni.template = '". $template ."'
GROUP BY ni.letter_id;
This change should also speed up your query significantly.
If it's allowed, why don't you create a new table called newsletter_item_receivers where you could store letter_id, receiver_id fields?
Having comma separated values in a field like this usually means you're missing a table :)
Edit:
By using CSV, you are making your life miserable when you want to retrieve an answer to "give me all newsletters that receiver_id=5 receives" :)
Here's a good answer to a similar question on SO: Comma separated values in a database field
Edit2:
If I understand your table relationships correctly then it would be something like this:
SELECT
a.letter_date,
b.receiver_id,
a.status
FROM newsletter_items_receivers b
LEFT OUTER JOIN newsletter_items a ON (a.letter_id = b.letter_id)
LEFT OUTER JOIN newsletter_mailgroups m ON (m.mailgroup_id = b.receiver_id)
NOTE! This query WILL NOT return a newsletter when there are no receivers of that newsletter.
If you need that functionality you can try something like this:
SELECT
x.letter_date,
y.mailgroup_name,
x.status
FROM (
SELECT
a.letter_date,
b.receiver_id,
a.status
FROM newsletter_items a
LEFT OUTER JOIN newsletter_items_rec b ON (b.letter_id = a.letter_id)) x
LEFT OUTER JOIN newsletter_mailgroups y ON (y.mailgroup_id = x.receiver_id)
I don't have access to SQL right now so I might have made some syntax errors (hopefully not logical ones :)).
As for why we are doing it like this, as #Konerak pointed out, you'd be well advised to read up on database normalization and why it's important.
You can start with this article from about.com, just glanced over it seems an OK read
http://databases.about.com/od/specificproducts/a/normalization.htm
Also, it would be good if you'd keep fields names the same across multiple tables.
For example you have letter_id in newsletter_items, but you have field_letter_uid in newsletter_fields. Just a thought :)
Try to use
SELECT A.*, B.*, group_concat(C.mailgroup_name SEPARATOR ',')
FROM newsletter_items A, newsletter_fields B, newsletter_mailgroups C
WHERE B.field_letter_uid = A.letter_id
AND field_name = 'letter_headline'
AND A.template = '". $template ."'
and find_in_set(c.mailgroup_id, A.receivers)
group by A.letter_id;

find likewise data from two tables in mysql

i have two tables in my database one is A other one is B
A is having few fields in which three are id,name,group
B is having feilds like id,title,description, etc.
i have to search the id's of title and description that are having data similar to table A's name or group and then have to insert the id's in a field of table A.
For example,
if A is having 'Anna' in its name and 'girl' in its group then i have to search the title's and descriptions in table B that are containing this word 'Anna' or 'girl'.
I want to do this in one single query.
How can i do so?
Edit:
Iam explainng my tables here for a better understanding
table A
id name group matched_id
1 anna girl
2 sydney girl
3 max boy etc.
Table B
id title description
1 A good girl Anna is a very good girl
2 Max doesnt work hard Boys are always like that only
etc...
see i will first search for a match for 'anna' in the table B's title and description and if a match is found in either of them then i'll store that id in table A only in the field 'matched id'
I'll do the same procedure for 'girl' and then for 'sydney' and so on
This query should do the trick:
UPDATE a SET matched_id =
(SELECT b.id FROM b
WHERE b.title LIKE CONCAT(' % ',a.name,' % ')
OR b.description LIKE CONCAT('% ',a.name,' %')
OR b.title LIKE CONCAT('%',a.group,'%')
OR b.description LIKE CONCAT('%',a.group,'%')
LIMIT 1)
WHERE EXISTS
(SELECT a.id FROM b
WHERE b.title LIKE CONCAT('% ',a.name,' %')
OR b.description LIKE CONCAT('% ',a.name,' %')
OR b.title LIKE CONCAT('%',a.group,'%')
OR b.description LIKE CONCAT('%',a.group,'%')
LIMIT 1)
Some remarks to this:
LIMIT 1 was necessary, as each subquery can and will return more than 1 row
Not 100% sure if the order you want/need is used, you may need some further testing for that and use order by if needed
it may also be better to use an extra table for the groups (to reduce duplicate entries) and maybe one extra mapping table, so that you can map all results from B to A
EDIT:
if names need to match perfectly (unlike girl/girls), you can just add a space in front of the name: '% ',a.name,' %'. If it gets more complicated I would suggest using regular expressions (REGEX). I modified the query with the spaces (for names only), so feel free to try it again.
SELECT *
FROM A
JOIN B
ON b.title IN (a.name, a.group)
OR b.description IN (a.name, a.group)
WHERE a.name = 'Anna'
AND a.group = 'girl'
Since INDEX_UNION's are not very efficient in MySQL, it may be better to split the queries (especially if your tables are InnoDB):
SELECT *
FROM (
SELECT b.id
FROM A
JOIN B
ON b.title IN (a.name, a.group)
WHERE a.name = 'Anna'
AND a.group = 'girl'
UNION
SELECT b.id
FROM A
JOIN B
ON b.description IN (a.name, a.group)
WHERE a.name = 'Anna'
AND a.group = 'girl'
) bo
JOIN B
ON b.id = bo.id

Categories