MySql: Multiple Queries to select one column from different table - mysql

mysql> select * from SC_rules;
+--------+--------+--------+---------------+
| old_SC | new_SC | fee_JD | offer_id_Flag |
+--------+--------+--------+---------------+
| 114 | 111 | 5.000 | 1 |
| 114 | 310 | 6.000 | 1 |
| 114 | 41 | 2.000 | 0 |
+--------+--------+--------+---------------+
mysql> select * from offer_rules;
+--------+--------+----------+-------+
| old_SC | new_SC | offer_id | price |
+--------+--------+----------+-------+
| 114 | 111 | 10 | 1.000 |
| 114 | 310 | 20 | 0.500 |
+--------+--------+----------+-------+
I want the price from SC_rules where offer_id_Flag =0 and the price from offer_rules where offer_id_flag =1 in once select.

You can use a conditional LEFT JOIN to achieve this, and COALESCE to get the first non-NULL result.
Something like this (not tested):
SELECT COALESCE(o.price, sc.price)
FROM SC_rules sc
LEFT JOIN offer_rules o ON o.old_SC = sc.old_SC AND sc.offer_id_Flag = 1
Basically, get the price from your offer_rules table (if it exists) otherwise get the price from your sc_rules table (btw this column seems to be missing from your source data in your question).
The JOIN works by matching the rows on the old_SC column but you should modify this to whichever column the primary\foreign key is. The important part is the join on sc.offer_id_Flag = 1, which only makes the join when the flag value is 1 (as you want).

SELECT `fee_JD` as 'price' FROM `SC_rules` WHERE `offer_id_Flag`.`SC_rules` = '0';
SELECT `price` FROM `offer_rules` WHERE `offer_id`.`SC_rules` = '1';
If you want multi queries.

Related

Combining three SQL queries into one

I got working code from three queries but I would like to combine them into one or two. Basically I am checking if a provided phone number exists in table contacts or leads as well as if it exists as a secondary number in customfieldsvalues (not all leads have a customfield value though). I am using a CRM system based on CodeIgniter.
What I want to do (non-correct/hypothetical query):
SELECT * FROM contacts OR leads WHERE phonenumber = replace(X, '-', '')
OR leads.id = customvaluefields.relid AND cfields.fieldid = 41 AND cfields.value = X
Tables
table : contacts
+-------+----------------+----------------+
| id | firstname | phonenumber |
+-------+----------------+----------------+
| 1 | John | 214-444-1234 |
| 2 | Mary | 555-111-1234 |
+-------+----------------+----------------+
table : leads
+-------+-----------+---------------------+
| id | name | phonenumber |
+-------+-----------+---------------------+
| 1 | John | 214-444-1234 |
| 2 | Mary | 555-111-1234 |
+-------+-----------+---------------------+
table : customvaluefields
+-------+-----------+-------------+-----------+
| id | relid | fieldid | value |
+-------+-----------+-------------+-----------+
| 1 | 1 | 41 | 222333444 |
| 2 | 1 | 20 | Management|
| 3 | 2 | 41 | 333444555 |
+-------+-----------+-------------+-----------+
If I understand what you are trying to, maybe UNION ALL would work. This is something to get you started:
SELECT C.ID, C.FirstName, C.Phonenumber
FROM Contacts C
JOIN CustomValueField CVF
ON c.ID = CVF.RelID AND
CVF.ID = 41
AND REPLACE(Phonenumber,'-','') = cvf.Value
UNION ALL
SELECT L.ID, L.FirstName, L.Phonenumber
FROM Leads L
JOIN CustomValueField CVF
ON L.ID = CVF.RelID AND
CVF.ID = 41
AND REPLACE(Phonenumber,'-','') = cvf.Value
I'm joining the contacts and leads tables to CustomeValueField in each query and then UNION them together along with the WHERE clause in each. I'm sure it's not 100% correct for what you need, but should get you headed to a solution. Here is more information: https://dev.mysql.com/doc/refman/8.0/en/union.html

MySQL: SUM function applied to a formula contained in field selected by another query

I'm in the need to perform a select SUM() where that is a formula contained into a field selected by another query.
Example:
table_A (the "formula" field contains, in each cell, an arithmetic expression involving columns from table B):
+------------+--------------+------------+
| Product_id | related_prod | formula |
+------------+--------------+------------+
| U1 | C2 | col2-col1 |
| U2 | C3 | col3-col2 |
| U3 | C4 | col3-col1 |
+------------+--------------+------------+
table_B:
+------------+---------+------------+----------+------+------+------+
| Product_id | year_id | company_id | month_id | col1 | col2 | col3 |
+------------+---------+------------+----------+------+------+------+
| C2 | 2017 | 1 | 2 | 100 | 200 | 300 |
| C3 | 2017 | 1 | 2 | 400 | 500 | 600 |
| C4 | 2017 | 1 | 2 | 700 | 800 | 900 |
+------------+---------+------------+----------+------+------+------+
I do, then, the following query:
SELECT
SUM(totals.relaz) as final_sum,
totals.relaz as 'col',
totals.prod as 'prod',
totals.cons as 'cons',
m.company_id, m.month_id, m.year_id, FROM `table_B` m,
( SELECT formula as relaz,
related_prod as prod,
p.product_id as cons FROM table_A p )
AS totals
WHERE m.product_id=totals.prod
GROUP BY m.company_id, m.year_id, m.month_id, m.product_id, totals.cons
After the select I'd do expect that, considering for example the only product 'U1', the corresponding row would be
+-----------+-----------+------+------+------------+----------+---------+
| final_sum | col | prod | cons | company_id | month_id | year_id |
+-----------+-----------+------+------+------------+----------+---------+
| 100 | col2-col1 | C2 | U1 | 1 | 2 | 2017 |
+-----------+-----------+------+------+------------+----------+---------+
Instead, what I get is
+-----------+-----------+------+------+------------+----------+---------+
| final_sum | col | prod | cons | company_id | month_id | year_id |
+-----------+-----------+------+------+------------+----------+---------+
| 0 | col2-col1 | C2 | U1 | 1 | 2 | 2017 |
+-----------+-----------+------+------+------------+----------+---------+
i.e. the final_sum field is always set to 0, despite the 'col' field contains the correct equation.
What am I doing wrong?
Thank you in advance
Alex
You are trying to get sum from a string column (table_A.formula). This will result 0. MySQL/MariaDB will not try to convert the strings to column references and evaluate the formula in the string.
Another thing is that you should list all columns not in aggregate function in GROUP BY.
To get the result you want, use:
SELECT
SUM(CASE
WHEN a.formula = 'col2-col1' THEN b.col2-b.col1
WHEN a.formula = 'col3-col1' THEN b.col3-b.col1
WHEN a.formula = 'col3-col2' THEN b.col3-b.col2
END
) AS final_sum,
a.formula as 'col',
a.related_prod as 'prod',
a.Product_id as 'cons',
b.company_id,
b.month_id,
b.year_id
FROM table_B b
JOIN table_A a on a.related_prod=b.Product_id
GROUP BY a.formula, a.related_prod, a.Product_id, b.company_id, b.month_id, b.year_id
It may possible to build a Stored routine that fetches the string col2-col1 and inserts it (using CONCAT) into a string, then PREPAREs and EXECUTEs the SQL string.
That is, dynamically build the SQL, perhaps like in #slaakso's Answer.
It would be messy.
I have needed something like this; I chose to do eval() in PHP, which was the client language. I use it for evaluating VARIABLES and GLOBAL STATUS. Example: Table_open_cache_misses / Uptime gives the "misses per second", which, if high, indicates the need for increasing the setting table_open_cache.

How to join tables with SQL query and take number of tied columns?

I'm having BookTable in database (with foregin hey LibID):
| BookID | BookName | BookPrice | LibID |
-------------------------------------------
| 1 | Book_1 | 200 | 1 |
| 2 | Book_2 | 100 | 1 |
| 3 | Book_3 | 300 | 2 |
| 4 | Book_4 | 150 | 4 |
and also LibraryTable:
| LibID | LibName | LibLocation |
-----------------------------------
| 1 | Lib_1 | Loc_1 |
| 2 | Lib_2 | Loc_2 |
| 3 | Lib_3 | Loc_3 |
| 4 | Lib_4 | Loc_4 |
I need to write SQL query that will return be the info about the library and number of books for that library:
| LibID | LibName | NumberOfBooks|
------------------------------------
| 1 | Lib_1 | 2 |
| 2 | Lib_2 | 1 |
| 3 | Lib_3 | 0 |
| 4 | Lib_4 | 1 |
It should be one SQL query, probably with nested queries or joins.. Not sure how the query should look like:
SELECT L.LibID AS LibID, L.LibName AS LibName, COUNT(B) AS NumberOfBooks
FROM LibraryTable L, BookTable B
WHERE L.LibID = B.LibID
Will that work?
No, this query will not work. COUNT aggregates data, so you must explicitely tell the DBMS for which group of data you want the count. In your case this is the library (you want one result record per library).
COUNT's parameter is a column, not a table, so change this to * (i.e. count records) or a certain column (e.g. LibID).
The join syntax you are using is valid, but deprecated. Use explicit joins instead. In your case an outer join would even show libraries that have no books at all, if such is possible.
select l.libid, l.libname, count(b.libid) as numberofbooks
from librarytable l
left outer join booktable b on b.libid = l.libid
group by l.libid;
You could also do all this without a join at all and get the book count in a subquery instead. Then you wouldn't have to aggregate. That's way simpler and more readable in my opinion.
select
l.libid,
l.libname,
(select count(*) booktable b where b.libid = l.libid) as numberofbooks
from librarytable l;
SELECT lt.LibID AS LibID, lt.LibName AS LibName, count(*) AS NumberOfBooks
FROM BookTable AS bt
LEFT JOIN LibraryTable AS lt ON bt.LibID = lt.LibID
GROUP BY bt.LibID

Merging info from two queries into a single table

Query 1:
SELECT num_requerimiento, asunto
FROM masivos_texto INNER JOIN envios_masivos
ON id_masivos=id_envio;
Result 1:
+---------------------+---------------------+
| num_requerimiento | asunto |
|---------------------+----------------------
| 1800 | inscripcion |
|---------------------+---------------------+
| 1801 | seguimiento |
+---------------------+---------------------+
Query 2:
SELECT id_envio, estatus, count(estatus)
FROM acuses_recibo
WHERE id_envio IN (SELECT id_masivos FROM cati_atencion.masivos_texto WHERE fecha >= '2014-01-01' AND fecha <= '2015-06-16')
GROUP BY id_envio, estatus;
Result 2:
+---------------------+---------------------+----------------------+
| id_envio | estatus | count(estatus) |
|---------------------+--------------------------------------------+
| 84 | 0 | 4031 |
|---------------------+---------------------+----------------------+
| 84 | 1 | 632 |
+---------------------+---------------------+----------------------+
| 85 | 0 | 35635 |
+---------------------+---------------------+----------------------+
| 85 | 1 | 3711 |
+---------------------+---------------------+----------------------+
Desired Result:
+---------------------+-----------------+------------+------------+-------------------+
| num_requerimiento | asunto | id_envio | estatus | count(estatus) |
|---------------------+-----------------+------------+------------+-------------------+
| 1800 | inscripcion | 84 | 0 | 4031 |
|---------------------+-----------------+------------+------------+-------------------+
| 1800 | inscripcion | 84 | 1 | 632 |
+---------------------+-----------------+------------+------------+-------------------+
| 1801 | seguimiento | 85 | 0 | 635 |
+---------------------+-----------------+------------+------------+-------------------+
| 1801 | seguimiento | 85 | 1 | 711 |
+---------------------+-----------------+------------+------------+-------------------+
in the Desired Result the id_envio/id_masivos corresponding to num_requerimiento 1800 is 84,
and the id_envio/id_masivos corresponding to num_requerimiento 1801 is 85,
and estatus in the 2nd table cant take up to three values, than i.a. for your assistance.
UNION doesn´t work, it gives me the 1st table followed by the 2nd, and only if the selects are of the same number of columns.
To do this with SQL, you will need a table relating your masivos_texto and acuses_recibo tables. I suggest you create a table. You could call it req_id or anything suitable. This is often called a JOIN table. It will have this content
num_requerimiento id_envio
1800 84
1801 85
Then you'll be able to join your first and second queries together appropriately.
It's not possible to write your query for you without knowing the rows of your tables.
Solved!! I needed to use aliases to each SELECT, as adding an alias to each select level, like this:
SELECT result1.num_requerimiento, result1.asunto, result1.id_masivos, result2.estatus, result2.conteo
FROM
(SELECT C.num_requerimiento, B.asunto, B.id_masivos
FROM masivos_texto B INNER JOIN envios_masivos C
ON B.id_masivos=C.id_envio) as result1
INNER JOIN
(SELECT A.id_envio, A.estatus, count(estatus) as conteo
from acuses_recibo A
WHERE A.id_envio IN (SELECT B.id_masivos FROM masivos_texto B where B.fecha >= '2014-01-01' AND B.fecha <= '2015-06-16')
GROUP BY A.id_envio, A.estatus) as result2
ON result1.id_masivos=result2.id_envio;
and that generates the 3rd table needed. Hope it helps someone in the future.

Merging Corresponding MySQL Records

I have a MySQL table called "objecttable" that has the following structure and data in it. (The data is just a sequence, there is a whole lot more).
ID | Name | posX | posY | posZ |rotX | rotY | rotZ | rotW |
3562 | LODpmedhos1_LAe | 2062 | -1703 | 16 | 0 | 45 | 22 | 1 |
3559 | LODpmedhos5_LAe | 2021 | -1717 | 15 | 0 | 45 | 34 | 1 |
3561 | LODpmedhos3_LAe | 2021 | -1717 | 15 | 0 | 45 | 34 | 1 |
I want to figure out which records have the same posX, posY, posZ, rotX, rotY and rotZ values and insert them into a table called "matchtable", and in the end I want it to look like this (I have the table structure ready)
ID1 | Name | ID2 | Name |
3559 | LODpmedhos5_LAe | 3561 | LODpmedhos3_LAe|
I'd appreciate if someone could give me the correct SQL query for it. I don't have more than two matching coordinates and not all coordinates match.
Sorry if the table representations suck, I'll try to make a HTML table if necessary.
Thanks!
This query will do the trick, but the number of results might be a LOT more than required. For example, if there are 5 rows satisfying your query, then the results will be 20( = n*(n-1) ) in number.
SELECT ot.ID AS ID1, ot.Name AS Name1, ot2.ID AS ID2, ot2.Name AS Name
FROM objecttable ot
JOIN objecttable ot2
ON ot.ID > ot2.ID
AND ot.posX = ot2.posX
AND ot.posY = ot2.posY
AND ot.posZ = ot2.posZ
AND ot.rotX = ot2.rotX
AND ot.rotY = ot2.rotY
AND ot.rotZ = ot2.rotZ
EDIT
In reply to lserni's comment:
ON ot.ID <> ot2.ID
The above condition is there to remove the result like:
ID1 | Name | ID2 | Name |
3559 | LODpmedhos5_LAe | 3559 | LODpmedhos5_LAe|
try this:
-- insert into matchtable -- uncomment to insert the data
select alias1.Id,
alias1.Name,
alias2.Id
alias2.Name
from objecttable as alias1
join objecttable as alias2
on alias1.posx = alias2.posx
and alias1.posy = alias2.posy
and alias1.posz = alias2.posz
and alias1.roty = alias2.roty
and alias1.roty = alias2.roty
and alias1.rotz = alias2.rotz
and alias1.Id > alias2.Id