I have orders, order_attachments, order_preship_check, order_preship_check_attachment, order_log, order_log_attachments tables
The only common thing in these columns are order_id. Right now in the query I am only checking those order_attachments which are type 1 and type 2 using the following query
SELECT
COUNT(file_id) AS totalFiles
FROM
orders_files
WHERE
order_id = '88125'
AND attachment_type IN ('1', '2')
So if it returns I show an ATTACHMENTS icon with that order. Now I need to combine preship attachments and log attachments in this as well. There are no additional checks, individual queries for both are as follows
SELECT
COUNT(file_id) AS totalFiles
FROM
orders_preship_check_attachment
WHERE
order_id = '88125'
and
SELECT
COUNT(id) AS totalFiles
FROM
orders_log_attachment
WHERE
order_id = '88125'
I need to combine these 3 queries in one query. So if each table have 1 records, I just need to get the count of 3, even 3 is not important. Means if any of these records have attachments I need to show the icon, TRUE or FALSE. I hope it makes it more clear
Try this
SELECT SUM(totalFiles) AS totalFiles
FROM (
SELECT COUNT(file_id) AS totalFiles
FROM orders_files
WHERE order_id = '88125' AND
attachment_type IN ('1', '2')
UNION ALL
SELECT COUNT(file_id) AS totalFiles
FROM orders_preship_check_attachment
WHERE order_id = '88125'
UNION ALL
SELECT COUNT(id) AS totalFiles
FROM orders_log_attachment
WHERE order_id = '88125'
) t
or
SELECT COUNT(file_id) AS totalFiles
FROM (
SELECT file_id
FROM orders_files
WHERE order_id = '88125' AND
attachment_type IN ('1', '2')
UNION ALL
SELECT file_id
FROM orders_preship_check_attachment
WHERE order_id = '88125'
UNION ALL
SELECT id
FROM orders_log_attachment
WHERE order_id = '88125'
) t
Use UNION or UNION ALL but this must have the same type and number of columns.
Example code:
SELECT 'Customer' AS type, id, name FROM customer
UNION ALL
SELECT 'Supplier', id, name FROM supplier
If your query contains different number of columns try using joins.
Related
I have a query that captures customer ids from three tables (each table is a different contact method).
I want to get the count of distinct customer ids after the unions.
The SQL statement below is working and returns a list of unique customer ids (no dups):
SELECT DISTINCT customer_id
FROM email_contact
WHERE info_id = 1
AND status = 'SENT'
UNION
SELECT DISTINCT customer_id
FROM call_contact
WHERE info_id = 1
AND status = 'CALLED'
UNION
SELECT DISTINCT customer_id
FROM mail_contact
WHERE info_id = 1
AND status = 'MAILED'
From that query I want a count of customers, but my attempts to wrap the query in a select count keep producing syntax errors. How can wrap the unions to provide me with a count of the clients?
I would recommend:
SELECT COUNT(DISTINCT customer_id)
FROM (
SELECT customer_id FROM email_contact WHERE info_id = 1 AND status = 'SENT'
UNION ALL SELECT customer_id FROM call_contact WHERE info_id = 1 AND status = 'CALLED'
UNION ALL SELECT customer_id FROM mail_contact WHERE info_id = 1 AND status = 'MAILED'
) t
I removed the DISTINCT and I changed the UNIONs to UNION ALL, so the database just gathers all the rows from the 3 union members without attempting to manage duplicates (this is fast). Then, you can use COUNT(DISTINCT ...) in the outer query.
You can wrap it like this
SELECT COUNT(*)
FROM
( SELECT DISTINCT customer_id
FROM email_contact
WHERE info_id = 1
AND status = 'SENT'
UNION
SELECT DISTINCT customer_id
FROM call_contact
WHERE info_id = 1
AND status = 'CALLED'
UNION
SELECT DISTINCT customer_id
FROM mail_contact
WHERE info_id = 1
AND status = 'MAILED') t1
Is this what you ant?
SELECT COUNT(*)
FROM ((SELECT customer_id
FROM email_contact
WHERE info_id = 1 AND status = 'SENT'
) UNION -- on purpose to remove duplicates
(SELECT customer_id
FROM call_contact
WHERE info_id = 1 AND status = 'CALLED'
) UNION
(SELECT customer_id
FROM mail_contact
WHERE info_id = 1 AND status = 'MAILED'
)
) c;
Note that all your DISTINCTs are unnecessary because UNION removes duplicates.
I have two MySQL tables. Each table has the following fields:
p_id
hours_value
minute_value
I want to sum of the hours and minutes field of these two tables for a p_id or project_id. Below query did not provide me the expected result.
SELECT SUM(hours_value), SUM(minute_value)
FROM timesheet_master
UNION
SELECT `hours_value`
FROM timesheet_master_archive
WHERE `p_id` = '1'
I suppose you want to union the rows and then calculate the sums? That would be:
select sum(hours_value), sum(minute_value)
from
(
select hours_value, minute_value from t1 where p_id = 1
union all
select hours_value, minute_value from t2 where p_id = 1
) both_tables;
You can try below - for union, your no of columns should be equal in both select query
SELECT SUM(hours_value) as hrval, SUM(minute_value) as minval
FROM timesheet_master
UNION
SELECT `hours_value`,minute_value
ROM timesheet_master_archive WHERE `p_id` = '1'
The query I found:
SELECT SUM(hours_value) as hrval, SUM(minute_value) as minval
FROM timesheet_master WHERE `p` = '1'
UNION
SELECT `hours_value`,minute_value
FROM timesheet_master_archive WHERE `p_id` = '1'
There are no rows for this product_id. Result returns no rows instead of SUM = 0.
SELECT COALESCE(SUM(amount), 0) FROM store2product WHERE product_id = 6706434 GROUP BY product_id;
Is there a way to get result = 0?
There is no record for product_id = 6706434 in table store2product. As you group by product_id, you get one result row per product_id found with this query. As the product_id is not found, no row is returned.
Simple solution: remove GROUP BY.
SELECT
COALESCE(SUM(amount), 0)
FROM store2product
WHERE product_id = 6706434;
Now you get one result row in any case.
Try this Trick..
Schema for your case
CREATE TABLE #TAB (ID INT, AMT DECIMAL(18,2))
INSERT INTO #TAB
SELECT 1,1200
UNION ALL
SELECT 1,120
UNION ALL
SELECT 3, 100
Now query the table like
SELECT SUM(ISNULL(AMT,0)) AS AMT FROM (
SELECT ID, SUM(AMT)AMT FROM #TAB WHERE ID =2 GROUP BY ID
UNION ALL
SELECT NULL AS ID, NULL AS AMT
)A
let's say I have the following Table:
ID, Name
1, John
2, Jim
3, Steve
4, Tom
I run the following query
SELECT Id FROM Table WHERE NAME IN ('John', 'Jim', 'Bill');
I want to get something like:
ID
1
2
NULL or 0
Is it possible?
How about this?
SELECT Id FROM Table WHERE NAME IN ('John', 'Jim', 'Bill')
UNION
SELECT null;
Start by creating a subquery of names you're looking for, then left join the subquery to your table:
SELECT myTable.ID
FROM (
SELECT 'John' AS Name
UNION SELECT 'Jim'
UNION SELECT 'Bill'
) NameList
LEFT JOIN myTable ON NameList.Name = myTable.Name
This will return null for each name that isn't found. To return a zero instead, just start the query with SELECT COALESCE(myTable.ID, 0) instead of SELECT myTable.ID.
There's a SQL Fiddle here.
The question is a bit confusing. "IN" is a valid operator in SQL and it means a match with any of the values (see here ):
SELECT Id FROM Table WHERE NAME IN ('John', 'Jim', 'Bill');
Is the same as:
SELECT Id FROM Table WHERE NAME = 'John' OR NAME = 'Jim' OR NAME = 'Bill';
In your answer you seem to want the replies for each of the values, in order. This is accomplished by joining the results with UNION ALL (only UNION eliminates duplicates and can change the order):
SELECT max(Id) FROM Table WHERE NAME = 'John' UNION ALL
SELECT max(Id) FROM Table WHERE NAME = 'Jim' UNION ALL
SELECT max(Id) FROM Table WHERE NAME = 'Bill';
The above will return 1 Id (the max) if there are matches and NULL if there are none (e.g. for Bill). Note that in general you can have more than one row matching some of the names in your list, I used "max" to select one, you may be better of in keeping the loop on the values outside the query or in using the (ID, Name) table in a join with other tables in your database, instead of making the list of ID and then using it.
just a quick question:
i have to have one single query that has multiple rows - some rows are identicle - and the order of rows must be preserved in the result -
some idea of what im refering to:
SELECT id,date
FROM items
WHERE id IN (1,2,1,3)
ORDER BY id=1 DESC,id=2 DESC,id=1 DESC,id=3 DESC;
unfortunately mysql result is this:
1,2,3
not 1,2,1,3
it removes the duplicate which i have to have in my result to display in multiple panels on the same webpage -
i really dont want to loop thru each id one by one to get them the way i want to display -
is there a way to actually have one single query that will preserve the order and pull out rows based on request whether its unique or not -
Your query as it stands will never work, because duplicate values in a list of values of an IN clause are ignored. The only way to make this work is by using UNION ALL:
SELECT id, date FROM items where id = 1
UNION ALL
SELECT id, date FROM items where id = 2
UNION ALL
SELECT id, date FROM items where id = 1
UNION ALL
SELECT id, date FROM items where id = 3;
But to be frank, I suspect your data model so far past screwed it's unusable.
try
SELECT
id,
date
FROM items
WHERE id IN (1,2,1,3)
ORDER BY FIND_IN_SET(id, '1,2,1,3')
Another scrupulous way to answer a suspicious question:
SELECT
items.id,
items.date
FROM
items
JOIN
( SELECT 1 AS id, 1 AS ordering
UNION ALL
SELECT 2, 2
UNION ALL
SELECT 1, 3
UNION ALL
SELECT 3, 4
) AS auxilary
ON
auxilary.id = items.id
ORDER BY
auxilary.ordering
Another approach (untested, but should give you the idea):
CREATE TEMPORARY TABLE tt (id INT, ai int unsigned auto_increment primary key);
INSERT INTO tt (id) VALUES (1), (2), (1), (3);
SELECT
id,
date
FROM items JOIN tt USING (id)
ORDER BY tt.ai;
keeps the given order.
If you want to include the records with id=1 and the order doesn't matter as long as you get them, you can split your query into two queries, one for (1,2,3) union all the other query for id=1 or just do:
... In (1,2)
Union all
... In (1,3)
Example:
Select * from
(Select case id when 1 then 1 when 2 then 2 as pseudocol, othercolumns
From table where Id in (1,2)
Union all
Select case id when 1 then 3 when 3 then 4 as pseudocol, othercolumns
From table where Id in (1,3)) t order by pseudocol
Instead of doing what you are trying to, just select the unique rows you need. In the frontend code, store each unique row once in a key=>value structure, where key is the item ID and value is whatever data you need about that item.
Once you have that you can use frontend logic to output them in the desired order including duplicates. This will reduce the amount of redundant data you are trying to select.
For example This is not usable code - exact syntax required depends on your scripting language
-- setup a display order
displayOrder= [1,2,1,3];
-- select data from database, order doesn't matter here
SELECT id,date
FROM items
WHERE id IN (displayOrder);
-- cache the results in a key=> value array
arrCachedRows = {};
for (.... each db row returned ...) {
arrCachedRows[id] = date;
}
-- Now output in desired order
for (listIndex in displayOrder) {
-- Make sure the index is cached
if (listIndex exists in arrCachedRow) {
echo arrCachedRows[listIndex ];
}
}
If you must persist in using UNION despite my warnings
If you go against the above recommendation and absolutely MUST have them back in 1 query in that order then add on an additional row which will enforce the row order. See below query where I use variable #subIndex to add an incrementing value as subIndex. This in turn lets you reorder by that and it'll be in the requested order.
SELECT
i.*
FROM (
SELECT #subIndex:=#subIndex+1 AS subIndex, id, date FROM items where id = 1
UNION
SELECT #subIndex:=#subIndex+1 AS subIndex, id, date FROM items where id = 2
UNION
SELECT #subIndex:=#subIndex+1 AS subIndex, id, date FROM items where id = 1
UNION
SELECT #subIndex:=#subIndex+1 AS subIndex, id, date FROM items where id = 3
) AS i,(SELECT #subIndex:=0) v
ORDER BY i.subIndex
Or a slightly cleaner version that keeps item selection until the outside and hides the subindex
SELECT
items.*
FROM items
-- initialise variable
INNER JOIN (SELECT #subIndex:=0) v
-- create a meta-table with the ids desired in the order desired
INNER JOIN (
SELECT #subIndex:=#subIndex+1 AS subIndex, 1 AS id
UNION
SELECT #subIndex:=#subIndex+1 AS subIndex, 2 AS id
UNION
SELECT #subIndex:=#subIndex+1 AS subIndex, 1 AS id
UNION
SELECT #subIndex:=#subIndex+1 AS subIndex, 3 AS id
) AS i
ON i.id = items.id
-- order by the subindex from i
ORDER BY i.`subIndex` ASC