How to dynamically create a pivot table on MySQL - mysql

I'm having difficulties creating the result i want on a specific situation.
I have a two tables:
1: sales by warehouse:
+-------------+---------------+--------------+
warehouse | type -------- | value
+-------------+---------------+--------------+
A--------------XX-------------234234----------
A-------------- YY------------ 234343--------------
A-------------- ZZ------------ 534534--------------
B-------------- XX------------ 234432--------------
B-------------- YY------------ 767563--------------
B-------------- ZZ------------ 312332--------------
c-------------- XX------------ 234234--------------
....
2: users by warehouse:
user--------|---warehouse
john--------|-- A
john--------|-- B
john--------|-- C
peter-------|-- A
Daniel------|-- C
Kim---------|-- B
Kim---------|-- C
....
So i created this query:
select a.warehouse, type, value from sales_by_warehouse A
left join users_warehouse B
ON A.warehouse=B.warehouse
where b.user = 'user_logged_on_software'
This works perfectly by giving me the warehouse that the user has access to and its values but, now, i wanted to invert the result such as in a pivot table so that if the user was Peter, this would be the result:
type--|-----A----
XX----|-----123123
YY----|-----3423423
ZZ----|-----3423345
And if the user was kim:
type--|-----B---------|-----C
XX----|-----123123-|---234324
YY----|-----423423-|---245435
ZZ----|-----423345-|---456233
Is there a way to do this with only select statements, without views or PS?

Related

How to transform SQL code into a measure?

Right now i am using 3 CSV files ( appointment, Person and Referral ) to calculate what i have called as KPI4, KPI5 and KPI6.
I import them into an Access Database that run some SQL queries. I want to automate this proces a bit and create a measure for these KPI's and just upload/update the 3 csv files and the POWER BI report just get updated.
For example for KPI4 I have the following SQL's queries
First and the main one but which refers to z_KPI8_part1 :
SELECT
Person.LPTID, Person.ccgName, Person.Caseload, t1.FTDate,
t1.SERVICEID, Person.LTCondition, Referral.Caseload, *
FROM
Person
INNER JOIN ((SELECT SERVICEID,FTDate
FROM z_KPI8_part1) AS t1
INNER JOIN Referral
ON t1.SERVICEID = Referral.SERVICEID)
ON Person.LPTID = Referral.LPTID;
z_KPI8_part1 which referrs to z_FirstTreatmentDate :
SELECT
z_FirstTreatmentDate.SERVICEID, Min(z_FirstTreatmentDate.FTDate) AS FTDate,
Max(Appointment.ATTENDANCE) AS ATTENDANCE
FROM
Appointment
INNER JOIN z_FirstTreatmentDate
ON (Appointment.SERVICEID = z_FirstTreatmentDate.SERVICEID) AND
(Appointment.Appointment = z_FirstTreatmentDate.FTDate)
WHERE
(((z_FirstTreatmentDate.FTDate) Between [forms]![frmMain]![txtFTDateFrom] And
[forms]![frmMain]![txtFTDateTo]))
GROUP BY
z_FirstTreatmentDate.SERVICEID;
z_FirstTreatmentDate :
SELECT
Appointment.SERVICEID, Min(Appointment.APPOINTMENT) AS FTDate,
Min(Appointment.APPTYPE) AS APPTYPE
FROM
(SELECT *
FROM Appointment
WHERE
(Appointment.APPTYPE=02 OR Appointment.APPTYPE=03 OR Appointment.APPTYPE=05) AND
(Appointment.ATTENDANCE='5' OR Appointment.ATTENDANCE='6')
) AS [%$###_Alias]
GROUP BY
Appointment.SERVICEID;
In theory KPI4 is First Appointment Date when client's Session Type ( APPTYPE )is one of the following: 2,3,5
And
Attendance Status is one of the following: 5 and 6.
From my method i am not getting anywhere near the numbers i get from Access database.
Please help me or guide me

Mapping two table ,React or Sql?and how?

Hi there I do have one table called user with the following :
cust_num|trans_num|date_of_transaction|price_of_product|id_of_product
and another table called customer with the following:
cont_id|transaction_id|transaction_date|prod_price_net|prod_id
basically I want to map trough it, in the end I would like to have another table with the mapped values,so joind...
and having this :
Sum of distinct “cust_num”
Sum of distinct “trans_num”
Average basket of transactions “avg_transactions”
in another table or as query so that I can ask the database that sum and average #.#
Thanks for the help guys much appreciated.
following the suggestion to give example here we go :
user tb
cust_num|trans_num|date_of_transaction|price_of_product|id_of_product
100504335|100503936|10/11/2019|67023|100059589
100406909|100402572|3/30/2017|1101|101101914
100006079|100007232|5/21/2013|8530|100055307
customer tb
cont_id|transaction_id|transaction_date|prod_price_net|prod_id
100504335|100503936|10/11/2019|67023|100059589
100406909|100402572|3/30/2017|1101|101101914
100006079|100007232|5/21/2013|8530|100055307
100202212|100202600|4/28/2018|470|101101914
100003470|100019059|3/19/2019|20844|790199694
100003470|100003687|9/8/2010|20000|790005573 0
mapped tb
c_id| t_id| t_d| p_pe_n| p_id
100504335|100503936|10/11/2019|67023|100059589
100406909|100402572|3/30/2017|1101|101101914
100006079|100007232|5/21/2013|8530|100055307
100202212|100202600|4/28/2018|470|101101914
100003470|100019059|3/19/2019|20844|790199694
100003470|100003687|9/8/2010|20000|790005573
result
sum_price_cust| sum_of_t| avg_t
67023|1|1
1101|1| 1
8530|1| 1
470|1| 1
20844+20000|2| 2
Should be something like this:
SELECT SUM(m.price_of_product) as sum_price_cust,
COUNT(m.cust_num) as sum_of_t,
SUM(m.price_of_product) / COUNT(m.cust_num) as avg_t
FROM (SELECT u.cust_num, u.trans_num, u.date_of_transaction, u.price_of_product, u.id_of_product
FROM user u
UNION ALL
SELECT c.*
FROM customer c
) m
GROUP BY m.cust_num
Not quite sure if average number is what you want though.

Can I craft a statement to return records where (attribute A = A1 and attribute B = B1) OR (attrbt A = A2 and attrbt B = B2) OR etc etc?

User has given me a table of vendor #s and Invoice #s, and wants a query to find the documents with those attributes. Tried just giving him:
select * from document.docdata
join document.documents.vendor #s
join document.documents.invoice #s
Where
vendor # in (paste in column A from his table)
AND
invoice # in (paste in column b from his table)
But that didn't do the trick, because he's wanting to see the docs whose vendor# and invoice# match the rows of the table, as in vendor#, invoice# = A1, B1. My first question was "Why not just search by the invoice# and be done with it?"
But turns out the invoice numbers aren't unique.
So I'm needing a better way of writing this:
Select * from table
join vendor #s
join invoice #s
Where
(Vendor#=A1 AND Invoice#=B1)
OR
(Vendor#=A2 AND Invoice#=B2)
....
OR
(Vendor#=A652 AND Invoice#=B652)
For sample data, here's an example with the first 10 items from the user. I have this data in csv format.
A | B
---------------------
354055 | 1637
259769 | 2112
259769 | 2314
153060 | 47185
174829 | 63486
297719 | 4994-033017
203110 | 1360
292193 | 2058-09-1271
202308 | 60513
286641 | 1975
So I need the records that match both Company 354055 and Invoice 1637, as well as both Company 259769 and Invoice 2112, plus both Company 259769 and Invoice 2314, etc.
EDIT: I ended up just using excel to get 659 lines of "(Vendor#=x AND Invoice#=y) OR". Probably could run faster but it works, so off to production it goes.
MySQL supports tuple syntax:
Select *
from table join
vendor #s
on . . . join
invoice #s
on . . .
Where (#Vendor#, Invoice#) in ( (A1, B1), (A2, B2), . . . )
This is a rough answer, since we don't have good sample data or column names, but the general idea is, since you have an external table that matches invoice #s to vendor #s, you should import that data into a temporary table. Then you can join against the table for records where both conditions match in an efficient way.
There are also VALUES() expressions (formally: Table Value Constructors). You could use this to generate your query with a little less code: create the expression for your data as part of the SQL string, and then JOIN against that expression to accomplish the filter.
SELECT d.*
FROM document.docdata d
INNER JOIN (
VALUES
ROW(354055,'1637'),
ROW(259769,'2112'),
ROW(259769,'2314'),
ROW(153060,'47185')
-- etc
) filter on filter.invoice = d.invoice and filter.company = d.company

Joining multiple tables in one

I'm revising my previous scenario, I want to know the serial details placed in SALES ORDER versus serial details order filled in DELIVERY RECEIPTS if its correct. There are three tables below, (1)TABLE A - this is my current output upon executing the script below. (2) TABLE B - another table that I want to join (TABLE B) because of serial details. (3) TABLE DESIRED output - i want to achive.. considering :
if basetype = 17 then it should insert serial in another column (SO_SERIAL)
and if basetype =15 then it should insert serial details in another coloumn (DR_SERIAL).
By means of this, I was able to analyze that serial used in SO is different/same as used in DR.
Thanks for your help.
select a.CardCode 'BPNAME', c.itemcode, a.DocEntry 'SO_DOCENTRY', a.DocNum 'SO Num', c.ObjType'SO_Btype',
b.docEntry 'DR_DOCENTRY',b.BaseRef 'DR_num',b.ObjType 'dr_type'
from ORDR a
LEFT join dln1 b on a.docentry = b.baseentry
left join RDR1 c on a.DocEntry = c.DocEntry
Table A.
BP ITEMCODE SO_DOCENTRY SO_NUM SO_BTYPE DR_DOCENTRY DR_NUM DR_TYPE
======================================================================================
CITALI TYB20001M 144900 20152733 17 130775 20152733 15
Table B.
SERIAL ITEMCODE BASEENTRY BASENUM BASETYPE QUANTITY CARDCODE
=====================================================================================
MCWF-12001-20120601 TYB20001M 144900 20152733 17 10.000000 CITALI
MBAL-13001-20130101 TYB20001M 130775 103073 15 5.000000 CITALI
Desired Output:
BP ITEMCODE SO_NUM SO_BTYPE SO_SERIAL DR_NUM DR_TYPE DR_SERIAL
============================================================================================
CITALI TYB20001M 20152733 17 MCWF-12001-20120601 20152733 15 AL-13001-20130101
By means of this, I was able to analyze that serial used in SO is different/same as used in DR.
To match so entries with dr entries you can join table b twice, first time take 'so' entries then second time take 'dr' entries. So you will get "header", "SoEntry", "DrEntry". Then you can compare them. Take this example
select t1.BP, t1.ITEMCODE, t21.Serial as SO_SERIAL, t22.SERIAL as DR_Serial
FROM table1 t1
LEFT JOIN table2 t21 on t21.ITEMCODE=t1.ITEMCODE and t21.BASETYPE=17
LEFT JOIN table2 t22 on t22.ITEMCODE=t1.ITEMCODE and t22.BASETYPE=15
You need to learn basic joins.
Definitely you will have to join these two table.
Here is a good link from where you can start with
http://www.w3schools.com/sql/sql_join.asp
https://stackoverflow.com/questions/7877720/the-best-tutorial-on-joins-in-mysql
I see your problem. you need to join over itemcode and BASETYPE.
so try this:
select A.BP
, A.ITEMCODE
, A.SO_NUM
, A.SO_BTYPE
, B.serial as SO_SERIAL
, A.DR_NUM
, A.DR_TYPE
, A.DR_SERIAL
from a
join b on a.itemcode = b.itemcode and a.so_btype = b.basetype

Dynamic Table Joining Based on Another Table Column Value?

I'm trying to figure out if there is a simple way to dynamically load a 2nd table based on the column value of the first table with mysql
Servers (Table 1):
ID | Game | Title
Servers_1 (Table 2, option 1):
server_id (links to servers.id) | game_version | players | plugins
Servers_2 (Table 2, option 2):
server_id (links to servers.id) | game_version | players | mods | game_map
Servers_etc. (Table 2, option etc.)
Trying to figure out how to do something like
left_join servers_[servers.game] on servers.id = servers_[servers.game].server_id
So it would grab the value of servers.game and use that to finish the table name. If this is not possible, then is a case statement possible such as:
Left_Join
if ( servers.game == 1 ) 'servers_1'
elseif ( servers.game == 2 ) 'servers_2'
elseif ( servers.game == 3 ) 'servers_3'
One option would be to LEFT JOIN each of the tables and use a CASE statement to return the appropriate data.
Something like this should help get you started:
SELECT S.Id, S.Game, S.Title,
CASE S.Game
WHEN 1 THEN S1.game_version
WHEN 2 THEN S2.game_version
END game_version,
...
FROM Servers S
LEFT JOIN Servers_1 S1 ON S.id = S1.Server_Id AND S.Game = 1
LEFT JOIN Servers_2 S2 ON S.id = S2.Server_Id AND S.Game = 2
Instead of using CASE, you could probably just use COALESCE as each Id/Game should be unique and only 1 wouldn't be NULL:
SELECT COALESCE(S1.game_version,S2.game_version,...) game_version
If there is no way the same server id can be in multiple tables, then you can leave the AND S.Game... out of the LEFT JOINs as it wouldn't longer be needed. Depends on your unique keys.
Alternatively, you could use Dynamic SQL.