Joining two Queries together in MySQL - mysql

I have two separate queries: Employee and Manager, which work perfectly fine and as I want but I wish to combine all the COLUMNS from both queries. Is this possible? I obviously don't expect a full answer but would appreciate some insight into possible methods to achieve this.
Employee Query:
SELECT
shopTableRef.shopname AS "Shop Name:",
perTableRef.personname AS "Employee Name:",
COUNT(inStoreTableRef.payid) AS "Total Sales:",
SUM(payTableRef.amount) AS "Sales Value (£):"
FROM
fss_Person perTableRef
JOIN
fss_Employee empTableRef ON perTableRef.personid = empTableRef.empid
JOIN
fss_InstorePayment inStoreTableRef ON empTableRef.empid = inStoreTableRef.empid
JOIN
fss_Payment payTableRef ON payTableRef.payid = inStoreTableRef.payid
JOIN
fss_Shop shopTableRef ON payTableRef.shopid = shopTableRef.shopid
WHERE
empTableRef.roleid = 2
GROUP BY
perTableRef.personname
ORDER BY
COUNT(inStoreTableRef.payid) DESC
Manager Query:
SELECT
perTableRef.personname AS "Manager's Name:"
FROM
fss_Person perTableRef
JOIN
fss_Employee empTableRef ON perTableRef.personid = empTableRef.empid
JOIN
fss_Manager manTableRef ON empTableRef.empid = manTableRef.empid
WHERE
empTableRef.roleid = 1
GROUP BY
perTableRef.personname
I have tried the following: UNION, UNION ALL, INNER JOIN, JOIN and nested queries but none seem to work.

UNION or UNION ALL should work with a couple of adjustments.
Each query must return the same number/type of columns, so fill in your Manager query with NULL AS "Shop Name:", etc. for the missing columns.
Only one ORDER BY is allowed for the combined queries, so make sure that comes at the very end, and refer to the ordering column by its aliased name "Total Sales:"

Related

MySQL query - more elegant option? Referencing same column name in multiple tables in a SELECT

I have several tables in a MySQL database for which most SELECT queries will reference a column of the same name for the same value in each table.
So for instance, the tables (bnsf, train_plan, train_type, and operation_costs) will ALL have a field called 'train_id'.
Depending on the record/row, the value on the 'train_id' column could be 1, 2, 3, 4, 5, etc. But most of the time in a query, the desired results will all be for the records where these values match a given value, such as "2".
So a query like this works:
SELECT * FROM (((bnsf
INNER JOIN train_plan ON bnsf.train_id = train_plan.train_id)
INNER JOIN train_type ON train_plan.train_id = train_type.train_id)
INNER JOIN operation_costs ON train_type.train_id = operation_costs.train_id)
WHERE bnsf.train_id = 2
AND train_plan.train_id = 2
AND train_type.train_id = 2
AND operation_costs.train_id = 2;
Is there a simpler way of writing that query (specifically the WHERE
clause)? Essentially, something like this:
WHERE `train_id` IN TABLE(bnsf, train_plan, train_type, operation_costs) = 2;
// invalid syntax
I'd like to avoid having AND, AND, AND - and having to repeat the same value for each table. What I have works but doesn't seem very elegant. Any ideas?
I've spent a long time reading other posts, but I'm not liking the suggestions with unions, etc. (Don't seem to be any shorter)
Your join conditions make all but the first WHERE clauses redundant.
INNER JOIN train_plan ON bnsf.train_id = train_plan.train_id)
Only train_plan rows matching the bnsf.train_id are selected, and similarly for
the other tables joined further.
So when you say,
WHERE bnsf.train_id = 2
And then you join the other tables on that column, you can be guaranteed that they'll all equal the same thing.
SELECT * FROM (((bnsf
INNER JOIN train_plan ON bnsf.train_id = train_plan.train_id)
INNER JOIN train_type ON train_plan.train_id = train_type.train_id)
INNER JOIN operation_costs ON train_type.train_id = operation_costs.train_id)
WHERE bnsf.train_id = 2
That's a perfectly reasonable query.

Sql Join query- setting default value if NOT in join query

I have a SQL query that links 2 tables to provide the data if a horse is in both the tables:
SELECT ProformSystem.TheDate as racedate,
ProformSystem.Course as course,
ProformSystem.TheTime as thetime,
ProformSystem.Horse as horse,
ATRSpeedRatings.rank as rank
FROM ATRSpeedRatings
INNER JOIN ProformSystem ON (ATRSpeedRatings.Horse = trim(ProformSystem.Horse)) AND (ATRSpeedRatings.TheDate = ProformSystem.TheDate) order by ProformSystem.TheTime;"
Is it possible that if the horse in ProformSystem.Horse is NOT in ATRSpeedRatings.Horse then I just make rank = 0 as a default value, or would I need to run a separate query?
This way I can display all horses from ProformSystem even if they don't have a rank in ATRSpeedRatings.
I think you want a left join and coalesce():
SELECT ps.TheDate as racedate, ps.Course as course, ps.TheTime as thetime,
ps.Horse as horse, COALESCE(sr.rank, 0) as rank
FROM ProformSystem ps LEFT JOIN
ATRSpeedRatings sr
ON sr.Horse = TRIM(ps.Horse) AND sr.TheDate = ps.TheDate)
ORDER BY ps.TheTime;
Note that this query uses table aliases. These make the query easier to write and to read.
Also, the JOIN condition sr.Horse = trim(ps.Horse) is highly suspect. You should fix the data so there are no spaces in ProformSystem. Fixing the data is more efficient and it will prevent problems on future queries.

Retrieve customer revenue

I want to create a report with the top 20 customers (based on revenue).
I am using the query:
SELECT dbo.CustTable.AccountNum
,dbo.dirpartytable.NAME
,dbo.hcmworker.PERSONNELNUMBER
,dbo.CustInvoiceJour.SALESBALANCE
,dbo.custinvoicejour.QTY
FROM dbo.CustTable
inner JOIN dbo.HCMWORKER ON dbo.HCMWORKER.RECID = dbo.CustTable.KEV_Worker
inner join dbo.custInvoiceJour on CustInvoiceJour.OrderAccount = CustTable.AccountNum
inner join dbo.dirpartytable on dirpartytable.recid = custtable.PARTY
where CustTable.KEV_Worker = '5633561745'
ORDER BY SalesBalanceMst DESC
I can't find the relation for the customer revenue, after all, that is how I want to sort the report. I am sorting on SalesBalanceMST right now while building the report. Also I am getting multiple records when executing this query.
What am i doing wrong?
EDIT: I now realize I am showing each Invoice Journal, how can I display the Total Revenue of the customer?
A similar search from AX 2012:
CustInvoiceJour CustInvoiceJour;
CustTable CustTable;
DirPartyTable DirPartyTable;
select forceLiterals generateonly sum(SalesBalanceMST), sum(Qty) from CustInvoiceJour
where CustInvoiceJour.OrderAccount == '102372200'
&& CustInvoiceJour.InvoiceDate > today()-365
join TableId from CustTable
group AccountNum
where CustTable.AccountNum == CustInvoiceJour.OrderAccount
join TableId from DirPartyTable
group Name
where DirPartyTable.RecId == CustTable.Party;
info(CustInvoiceJour.getSQLStatement());
This shows the following SQL:
SELECT SUM(T1.SALESBALANCEMST),SUM(T1.QTY),T2.ACCOUNTNUM,T3.NAME
FROM CUSTINVOICEJOUR T1
CROSS JOIN CUSTTABLE T2
CROSS JOIN DIRPARTYTABLE T3
WHERE (((T1.PARTITION=5637144576) AND (T1.DATAAREAID=N'xxx'))
AND ((T1.ORDERACCOUNT=N'102372200')
AND (T1.INVOICEDATE>{ts '2015-11-06 00:00:00.000'})))
AND (((T2.PARTITION=5637144576) AND (T2.DATAAREAID=N'xxx'))
AND (T2.ACCOUNTNUM=T1.ORDERACCOUNT))
AND ((T3.PARTITION=5637144576)
AND (T3.RECID=T2.PARTY))
GROUP BY T2.ACCOUNTNUM,T3.NAME
ORDER BY T2.ACCOUNTNUM,T3.NAME
What is different from your query:
no join on HcmWorker, as I do not have your custom field.
Using sum() to aggregate
selecting on InvoiceDate
selection on OrderAccount
selection on DataAreaId, really important for performance, implicit in AX
selection on Partition, really important for performance, implicit in AX
You cannot directly sort on a sum, but may on a nested SQL query.
I do not know exactly what is wrong in your query but perhaps this information can help you.
Check this standard report CustTopCustomersbyYTDSales, It has some good queries to do that.
https://technet.microsoft.com/en-us/library/hh389751.aspx

MySQL multiple joins and count distinct

I need to write query that joins several tables and I need distinct value from one table based on max count().
These are my tables names and columns:
bands:
db|name|
releases_artists:
release_db|band_db
releases_styles
release_db|style
Relations between tables are (needed for JOINs):
releases_artists.band_db = bands.db
releases_styles.release_db = releases_artists.release_db
And now the query that I need to write:
SELECT b.name, most_common_style
LEFT JOIN releases_artists ra ON ra.band_db = b.db
and here I need to find the most common style from all band releases
JOIN(
SELECT DISTINCT style WHERE releases_styles.release_db = ra.release_db ORDER BY COUNT() DESC LIMIT 1
)
FROM bands b
WHERE b.name LIKE 'something'
This is just a non working example of what I want to accomplish. It would be great if someone could help me build this query.
Thanks in advance.
EDIT 1
Each artist from table bands can have multiple records from releases_artists table based on band_db and each release can have multiple styles from releases_styles based on release_db
So if I search for b.name LIKE '%ray%' it returns something similar to:
`bands`:
o7te|Ray Wilson
9i84|Ray Parkey Jr.
`releases_artists` for Ray Wilson:
tv5c|o7te (for example album `Change`)
78wz|o7te (`The Next Best Thing`)
nz7c|o7te (`Propaganda Man`)
`releases_styles`
tv5c|Pop
tv5c|Rock
tv5c|Alternative Pop/Rock
----
78wz|Rock
78wz|Pop
78wz|Classic Rock
I need style name that repeats mostly from all artist releases as this artist main style.
Ok, this is a bit of a hack. But the only alternatives I could think of involve heaps of nested subqueries. So here goes:
SELECT name
, SUBSTRING_INDEX(GROUP_CONCAT(style ORDER BY release_count DESC SEPARATOR '|'), '|', 1) AS most_common_style
FROM (
SELECT b.db
, b.name
, rs.style
, COUNT(*) AS release_count
FROM bands b
JOIN releases_artists ra ON ra.band_db = b.db
JOIN releases_styles rs ON rs.release_db = ra.release_db
GROUP BY b.db, rs.style
) s
GROUP BY db;

Can anyone help me with a complex sum, 3 table join mysql query?

Hey guys I have a query and it works fine, but I want to add another table to the mix. The invite table I want to add has two fields: username and user_invite. Much like this site, I am using a point system to encourage diligent users. The current query which is displayed below adds the up votes and down votes based on the user in question: $creator. I want to count the number of entries for that same user from the invite table, and add 50 for each row it finds to the current output/sum of my query. Is this possible with one query, or do I need two?
"SELECT *,
SUM(IF(points_id = \"1\", 1,0))-SUM(IF(points_id = \"2\", 1,0)) AS 'total'
FROM points
LEFT JOIN post ON post.post_id=points.points_id
WHERE post.creator='$creator'"
This should work :
SELECT *,**SUM(IF(points_id = "1", 1,0))-SUM(IF(points_id = "2", 1,0))+(select count(*)*50
from inivite where username='$creator') AS 'total'**,
FROM points LEFT JOIN post ON post.post_id=points.points_id WHERE post.creator='$creator'"
Assuming that there might be no correspondence in invite table, I used outer join and coalesce:
SET #good='1', #bad='2', #creator='$creator';
SELECT *,
SUM(IF(points_id=#good, 1,0))-SUM(IF(points_id=#bad, 1,0))+COALESCE(inv_cnt, 0) * 50) AS total
FROM points
LEFT JOIN post
ON post.post_id=points.points_id
LEFT OUTER JOIN (SELECT username, COUNT(user_invite) as inv_cnt
FROM invite
GROUP BY username) invites
ON post.creator = invites.username
WHERE post.creator=#creator;
Designing this query with limited knowledge of the schema...
SELECT *,
SUM(IF(points_id = \"1\", 1,0))
-SUM(IF(points_id = \"2\", 1,0))
+ 50 * COUNT(invite.user_invite) AS 'total' <--
FROM points
LEFT JOIN post ON post.post_id=points.points_id <--
LEFT JOIN invite ON post.creator = invite.user_invite
WHERE post.creator='$creator'
The important thing here is the extra lines, which I've marked with "<--". One is for JOINing your two tables together, the other is to modify the argument of the SUM function.
Post back if this doesn't work.