Multiple SQL count requests, one query - mysql

I'm brand new to SQL and I know this should be easy, but I can't seem to find any reference on how to do specifically what I'm looking for. I've check the archives and I can't find a basic example.
Anyway, all I want is -
SELECT
(COUNT (i.productNumber WHERE i.type = 'type1') AS 'Type 1'),
(COUNT (i.productNumber WHERE i.type = 'type2') AS 'Type 2'),
FROM items AS i
WHERE i.dateadded BETWEEN '2015-03-02' and '2015-03-04'
The two count conditions are different, but both of those queries share that date condition. I've done two distinct select statements and put a UNION between them. That works. The only issue is all of the data appears in one column under the first alias in the statement. I would need each alias to be a new column. I also have to write the date condition in twice.

You could group them by type so you would get a different row for each of them :
SELECT i.type, COUNT(i.productNumber)
FROM items i
WHERE i.dateadded BETWEEN '2015-03-02' AND '2015-03-04'
GROUP BY i.type;
If you really want to have one row, then you could do
SELECT COUNT(b.productNumber) AS 'type1', COUNT(c.productNumber) AS 'type2'
FROM items i
LEFT JOIN items b on b.productNumber = i.productNumber
LEFT JOIN items c on c.productNumber = i.productNumber
WHERE i.dateadded BETWEEN '2015-03-02' AND '2015-03-04'
AND b.type = 'type1'
AND c.type = 'type2';

Related

SQL SELECT IN Array NodeJS

I have an array with results = ['5', '2', '11', '12', '4'];
Now I want to make get count SQL SELECTION based on such array, that is make the SELECT IN Array SQL command. I want to return number of of rows that are there in this array from each element, I tried
The SQL Command I tried so far is as in the image provided and my table.
The result you've got is exactly what I would expect from a COUNT statement. I think you forgot to add a GROUP BY company_two.
EDIT
To handle the case of companies not having any entry, you can do:
SELECT s.company_two_id, COUNT(s.id)
FROM supplies_table s
RIGHT OUTER JOIN companies_table c ON s.company_two_id = c.company_id
WHERE company_two_id IN (...)
GROUP BY s.company_two_id;
Try below :
select COALESCE(count(a), 0) from table1 where b in (something) group by b

Select only distinct values for a particular column mysql

We have two tables in mysql database.Screenshots are attached below.
Given table ads_testTable
here is the screenshot of my dimesnionvalue_flattable
We have to run a query like the one below.
SELECT Quiz_Attempt.L1_Key dimID,
Quiz_Attempt.L1_Label CatVars,
COALESCE(**xyz**,0) AS series0
FROM DSQ_ADSSCHEMA.ADS_TestTable dataTable
RIGHT OUTER JOIN LS_CONFIG.DSQ_DIMENSIONVALUES_FLAT Quiz_Attempt on dataTable.Quiz_Attempt = Quiz_Attempt.L1_Key
WHERE Quiz_Attempt.L0_Key = 'All Levels' AND
Quiz_Attempt.DimensionID = 'Packet'
GROUP BY Quiz_Attempt.L1_Key, Quiz_Attempt.L1_Label;
My motive is to write a query in place of xyz so that I can get avg of obtainedMarks column in testtable according to the value of dimID I get.Each distinct Quiz_Attempt is a different test so If a Packet is repeating for a particular Quiz_Attempt in testTable, it should take only one value for that AttemptID.
I think you query could take the form of:
SELECT
L1_Key dimID,
L1_Label CatVars,
COALESCE('**xyz**',0) AS series0
FROM (
SELECT *
FROM (SELECT * FROM ADS_TestTable GROUP BY ADS_TestTable.Quiz_Attempt) dataTable
RIGHT OUTER JOIN DSQ_DIMENSIONVALUES_FLAT Quiz_Attempt on dataTable.Quiz_Attempt = Quiz_Attempt.L1_Key
WHERE Quiz_Attempt.L0_Key = 'All Levels' AND
Quiz_Attempt.DimensionID = 'Packet'
GROUP BY dataTable.Quiz_Attempt
) A GROUP BY dimID, CatVars;
The JOIN is done in an inner query, and grouped by Quiz_Attempt, so that you get a single row per attempt. This result is then used to compute what you need.

Mysql: Create a view with multiple self joins without duplicates in result

Just to clarify i can't change the tables structure, so please leave out the "you should change your tables to this and that" answers, thank you.
So i have a table entities_attributes_values where an entity has a lot of attributes and the value of that attribute, basically imagine 3 fields:
entity_id
entity_attributes_id
value
Because every entities attribute and its value is on row getting more values is not so easy i was thinking of multiple self joins, and because this query will be very common i created a view, which is built with this query:
SELECT `L1`.`entity_id`,
`L1`.`value` as 'company_id',
`L2`.`value` as 'entity_name',
`P`.`value` as 'person_name',
`L4`.`value` as 'establishment_id',
`L5`.`value` as 'department_id'
FROM `entities_attributes_values` `L1`
LEFT JOIN `entities_attributes_values` `L2` ON `L1`.`entity_id` = `L2`.`entity_id` AND `L2`.`entity_attributes_id` = 1
LEFT JOIN `entities_attributes_values` `L3` ON `L1`.`entity_id` = `L3`.`entity_id` AND `L3`.`entity_attributes_id` = 3
LEFT JOIN `persons_attributes_values` `P` ON `L3`.`value` = `P`.`core_persons_id` AND `P`.`core_persons_attributes_id` = 4
LEFT JOIN `entities_attributes_values` `L4` ON `L1`.`entity_id` = `L4`.`entity_id` AND `L4`.`entity_attributes_id` = 12
LEFT JOIN `entities_attributes_values` `L5` ON `L1`.`entity_id` = `L5`.`entity_id` AND `L5`.`entity_attributes_id` = 13
WHERE `L1`.`entity_attributes_id` = 2
So this works but i have one problem i get "duplicate" values and its not really duplicate but the point is that in my view i want every entity to be only one row with all its attributes values but instead i get this:
So as you can see the first three result are not good for me, i only need the fourth one, where i have all my data about one entity.
Thank you in advance for any help!
Try using conditional aggregation instead:
select eav.entity_id,
max(case when entity_attributes_id = 2 then eav.value end) as company_id,
max(case when entity_attributes_id = 1 then eav.value end) as entity_name,
max(case when entity_attributes_id = 3 then eav.value end) as company_name,
. . .
from entities_attributes_values eav
group by eav.entity_id;
This will make it easy to add new attributes to the view. Also, don't use single quotes to delimit column names. Single quotes should only be used for date and time constants.

distinct in query repeating values

I wonder if anyone can spot the problem with this 'view' query to show only 'company' and 'materials'. The problem is that it shows each entry a separate time for each material and company. I'm using this view to populate a dropdown box in a form but I would only like it to show the distinct values for each column (company/materials) - as of now if, for example, end result is the company 'Anderson' twice but with different materials for each...it shows 'Anderson' twice. I've tried using DISTINCT after the select statement for each of the two, but I don't achieve what I want.
select `b`.`company` AS `company`, `bp`.`material` AS `material`
from (((`caseys_wrdp4`.`windows_brands_products` `bp`
left join `caseys_wrdp4`.`windows_brands` `b` on((`bp`.`brand_id` = `b`.`id`)))
join `caseys_wrdp4`.`Windows_last_submissions` `ls`)
join `caseys_wrdp4`.`windows_materials` `wm`)
where ((`bp`.`width` = round(`ls`.`width`,0))
and (`bp`.`height` = round(`ls`.`height`,0))
and (`bp`.`material` = `wm`.`name`)
and (`bp`.`type` = `ls`.`type`)
and if ((`ls`.`minimumbid` <> '0.00'),
(`bp`.`cost` between `ls`.`minimumbid` and `ls`.`maximumbid`),
(`bp`.`cost` <= `ls`.`maximumbid`)))
Possible answer:
Add GROUP_CONCAT and GROUP BY to your query:
select `b`.`company` AS `company`, GROUP_CONCAT(`bp`.`material`) AS `materials`
from (((`caseys_wrdp4`.`windows_brands_products` `bp`
left join `caseys_wrdp4`.`windows_brands` `b` on((`bp`.`brand_id` = `b`.`id`)))
join `caseys_wrdp4`.`Windows_last_submissions` `ls`)
join `caseys_wrdp4`.`windows_materials` `wm`)
where ((`bp`.`width` = round(`ls`.`width`,0))
and (`bp`.`height` = round(`ls`.`height`,0))
and (`bp`.`material` = `wm`.`name`)
and (`bp`.`type` = `ls`.`type`)
and if ((`ls`.`minimumbid` <> '0.00'),
(`bp`.`cost` between `ls`.`minimumbid` and `ls`.`maximumbid`),
(`bp`.`cost` <= `ls`.`maximumbid`)))
GROUP BY(`b`.`company`);
This will give you back a single row for each company w/ company and materials. materials will be a comma-separated list (#Barmar). You could then parse that field for the 2nd drop down.
Example Rows:
'Anderson' 'Wood,Vinyl'
'WM' 'Metal','Plastic'
Assuming you're building a webpage, depending on how you're building the DOM, you can either use javascript str.split(), https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split, or on the server side, any language should work.

Multiple columns in one subquery

I have a bit of a problem. I have a database layout like so:
customer
customer_id, name, age, etc...
customer_survey_question
id, category, caption, type
customer_survey_answer
id, customer_id, customer_survey_question_id, answer
and I need to pull in their answers like so:
name, age, etc..., question 1, question 2, question 3, etc...
Now I could do a sub-query:
SELECT
`customer`.*,
(
SELECT `answer`
FROM `customer_survey_answer`
WHERE `customer_survey_answer`.`customer_id`=`customer`.`customer_id`
AND `id`=1
) AS `question_1`,
(
SELECT `answer`
FROM `customer_survey_answer`
WHERE `customer_survey_answer`.`customer_id`=`customer`.`customer_id`
AND `id`=2
) AS `question_2`,
....
But there is 14 questions and I need to be able to do this pretty quickly and expand up to 80+ questions. What is the best way to approach?
You cannot do this through a query by and of itself.
Look here for some example code: How to merge data from 2 tables with MySQL
What you can do is use an INNER JOIN or GROUP_CONCAT and then reformat the data in your script (whether that be php or another language)
Using JOIN
Unser the circumstances this would likely lead to a large excess/irrelevant data in each row
SELECT c.*, csa.answer
FROM customers c
INNER JOIN
customer_survey_answer csa ON csa.`customer_id`=c.`customer_id`
ORDER BY c.customer_id, csa.customer_survey_question_id
Using GROUP_CONCAT
This will output one cell (csv style) as the answers
SELECT c.*, GROUP_CONCAT(csa.answer) as answers
FROM customers c
INNER JOIN
customer_survey_answer csa ON csa.`customer_id`=c.`customer_id`
GROUP BY c.customer_id
Using a loop
You might also consider querying the database for a list of customers with answers and then running a second query (for each customer returned) to get their answer. This could lead to a large number of queries.
First query:
SELECT * FROM customers
Second query:
SELECT answer
FROM customer_survey_answer
WHERE customer_id = INSERT_CUSTOMER_ID_HERE}
you want to pivot the data
SELECT class,GROUP_CONCAT(member)
FROM tbl
GROUP BY class;
is the basic case
http://www.artfulsoftware.com/infotree/queries.php#78
It is not wise to force DB output into result's columns.
In case you would like to operate over one only customer, make simple question query and then answer query to get everything and put it together outside of DB - in PHP for example.
In case you would like the list of customers with their answers, make first the question query and then make the "answer x customer" query with respective ids and put them together using hashing outside the DB. It works well and fast unless you don't use paging for your output list ;).
Hash can work like this
// suppose we have from database
// $answer_list(id,customer_id,customer_name,question_id,answer)
// $question_list(id,question)
// hash
$customer_list = array();
$customer_hash = array();
foreach ($answer_list as $answer)
{
$customer_id = $answer['customer_id'];
if (!isset($customer_hash[$customer_id]))
{
$customer_list[] = $customer_id;
$customer_hash[$customer_id]['name'] = $answer['customer_name'];
}
$customer_hash[$customer_id]['answer_hash'][$answer['question_id']] = $answer;
}
// output
foreach ($customer_list as $customer_id)
{
echo $customer_hash[$customer_id]['id'];
echo $customer_hash[$customer_id]['name'];
foreach ($question_list as $question)
{
echo $question['question'];
echo $customer_hash[$customer_id]['answer_hash'][$question['id]]['answer'];
}
}
If you want to generate a table in a single query you could use the group by on a query with a single INNER JOIN and then collect the values in several MAX( CASE ... END ) expressions. Sounds complicated at first but it does work reliably (just add another line for each desired column):
SELECT name, age,
MAX(CASE WHEN customer_survey_question_id=1 THEN answer END) a1,
MAX(CASE WHEN customer_survey_question_id=2 THEN answer END) a2,
MAX(CASE WHEN customer_survey_question_id=3 THEN answer END) a3,
MAX(CASE WHEN customer_survey_question_id=4 THEN answer END) a4,
MAX(CASE WHEN customer_survey_question_id=5 THEN answer END) a5,
MAX(CASE WHEN customer_survey_question_id=6 THEN answer END) a6,
MAX(CASE WHEN customer_survey_question_id=7 THEN answer END) a7,
MAX(CASE WHEN customer_survey_question_id=8 THEN answer END) a8,
...
FROM customer c INNER JOIN customer_survey_answer s
ON s.customer_id=c.customer_id