I am writing a program in java to fetch records from infobright database. Here are the table structure, query and the format of output I require.
Table structure:
column name type
------------ ----------
id integer
date integer
product_id integer
search_engine_id integer
visitor integer
example query:
select date,
product_id,
search_engine_id,
sum(visitor)
from report
where date in (201300910, 20130919)
group by search_engine_id,
product_id,
date
order by product_id,
date
The result set of the above query would be in the following format:
+----------+-------------+----------------+------------------+
| date | product_id | search_engine_id | sum(visitor) |
+----------+-------------+----------------+------------------+
| 20130910 | 108 | 2 | 7 |
| 20130910 | 108 | 1 | 15 |
| 20130919 | 108 | 1 | 2 |
| 20130919 | 108 | 2 | 3 |
| 20130910 | 107 | 1 | 3 |
| 20130910 | 107 | 2 | 2 |
| 20130919 | 107 | 1 | 2 |
| 20130919 | 107 | 2 | 3 |
| 20130919 | 106 | 1 | 10 |
There are two types of search_engine_id, that is 1 and 2.
For a given day, one product_id can exist two times at max, i.e., one record for search_engine_id 1 and other record for search_engine_id 2. What I want is to group the result with respect to product_id. So it would look something like:
+-------------------+-------------+----------------+------------------+
| date | product_id | search_engine_id | sum(visitor) |
+-------------------+-------------+----------------+------------------+
| 20130910,20130919 | 108 | 2,1,1,2 | 7,15,2,3 |
The main reason of doing this in the sql side is to make the data prepared for every product_id so that it will have less memory usage in java side. I have tried group_contact function but that seems to be not supported by infobright. Is there a way I can rewrite the query/make use of some other function to achieve this?
Related
I have 2 tables
Table1: customers:
-------------
| id | name |
-------------
| 1 | Mark |
-------------
| 2 | Tom |
-------------
| 3 | John |
Table2: sales:
-----------------------------------
|sid | customerid | price | state |
-----------------------------------
| 10 | 1 | 12000 | 0 |
-----------------------------------
| 11 | 2 | 13500 | 1 |
-----------------------------------
| 12 | 2 | 23000 | 1 |
-----------------------------------
| 13 | 3 | 26000 | 0 |
-----------------------------------
| 14 | 1 | 66000 | 1 |
-----------------------------------
the state column is 0=no dep and 1=dept
I want to list the customers that have DEPT by checking them in the sales table. Now i'm looping the customers and checking them one by one. and it works! but when the number of rows in the customer table grows the page slows down. i want to make this by an SQL query. can anyone help me please ?
the result will be like this:
Mark 66000
Tom 36500
By the Following query, you will get the same output as you want. The joining of tables will be executed on the filtered data using where condition
$this->db->select('customers.name,sum(sales.price)')
->from('customers')
->join('sales','sales.customerid = customers.id','left')
->where('sales.state !=0')
->group_by('customers.name');
->get()->result_array();
You can simply group by customer id in sales table. Code will be like this
return $this->db->select('MAX(customers.name) AS name, SUM(sales.price) as price')->join('sales', 'sales.customerid = customers.id')->where('sales.state', 1)->group_by('customers.id')->get('customers')->result();
I have a mySQL database table containing cellphones information like this:
ID Brand Model Price Type Size
==== ===== ===== ===== ====== ====
1 Apple A71 3128 A 40
2 Samsung B7C 3128 B 20
3 Apple ZX5 3128 A 30
4 Huawei Q32 2574 B 40
5 Apple A21 2574 A 25
6 Apple A71 3369 A 30
7 Samsung A71 7413 C 40
Now I want to create another table, that would contain counts for every possible combination of the parameters.
Params Count
============================================== =======
ALL 1000000
Brand(Apple) 20000
Brand(Apple,Samsung) 40000
Brand(Apple),Model(A71) 7100
Brand(Apple),Type(A) 6000
Brand(Apple),Model(A71,B7C),Type(A,B) 7
Model(A71) 12514
Model(A71,B7C) 26584
Model(A71),Type(A) 6521
Model(A71),Type(A,B) 8958
Model(A71),Type(A,B),Size(40) 85
And so on for every possible combination. I was thinking about creating a stored procedure (that i would execute periodically), that would perform queries with every existing condition like that, but I am a little stuck on how exactly should it look like. Or is there a better way how to do this?
Edit: the reason why I want to store information like this is to be able to show number of results in filter in client application, like in the picture.
I would like to create index on the Params column to be able to get the Count number for given hash instantly, improving performance.
I also tried querying and caching the values dynamically, but I want to try this approach as well, so I can compare which one is more effective.
This is how I am calculating the counts now:
SELECT COUNT(*) FROM products;
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple');
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple', 'Samsung');
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple') AND Model IN ('A71');
etc.
You can use a ROLLUP for this.
SELECT
model, type, size, COUNT(*)
FROM mytab
GROUP BY 1, 2, 3
WITH ROLLUP
With your sample data, we get the following:
| model | type | size | COUNT(*) |
| ----- | ---- | ---- | -------- |
| A21 | A | 25 | 1 |
| A21 | A | | 1 |
| A21 | | | 1 |
| A71 | A | 30 | 1 |
| A71 | A | 40 | 1 |
| A71 | A | | 2 |
| A71 | C | 40 | 1 |
| A71 | C | | 1 |
| A71 | | | 3 |
| B7C | B | 20 | 1 |
| B7C | B | | 1 |
| B7C | | | 1 |
| Q32 | B | 40 | 1 |
| Q32 | B | | 1 |
| Q32 | | | 1 |
| ZX5 | A | 30 | 1 |
| ZX5 | A | | 1 |
| ZX5 | | | 1 |
| | | | 7 |
The subtotals are present in the rows with null values in different columns, and the total is the last row where all group by columns are null.
This question already has answers here:
SQL: Repeat a result row multiple times, and number the rows
(9 answers)
Closed 3 years ago.
I have a table in MySQL that contains products ordered in an online store. I would like to generate a list of every ordered item, so I need to return multiple copies of a row based on the quantity of the item ordered:
+------------------+-------------+------------+-------+----------+
| order_product_id | order_id | product_id | model | quantity |
+------------------+-------------+------------+-------+----------+
| 2254 | 1427 | 56 | B-WO | 2 |
| 2253 | 1426 | 56 | B-WO | 2 |
| 2252 | 1425 | 56 | B-WO | 1 |
| 2251 | 1425 | 51 | 11 | 1 |
+------------------+-------------+------------+-------+----------+
Desired output, optionally including a counter for the item number out of the total:
+------------------+-------------+------------+-------+----------+------------------------+
| order_product_id | order_id | product_id | model | quantity | item number (optional) |
+------------------+-------------+------------+-------+----------+------------------------+
| 2254 | 1427 | 56 | B-WO | 2 | 1 |
| 2254 | 1427 | 56 | B-WO | 2 | 2 |
| 2253 | 1426 | 56 | B-WO | 2 | 1 |
| 2253 | 1426 | 56 | B-WO | 2 | 2 |
| 2252 | 1425 | 56 | B-WO | 1 | 1 |
| 2251 | 1425 | 51 | 11 | 1 | 1 |
+------------------+-------------+------------+-------+----------+------------------------+
Is there a straightforward MySQL way to do this?
If you are running MySQL 8.0+ (or MariaDB 10.2.2+), you can do this with recursive Common Table Expressions (CTE). It should look something like this:
WITH RECURSIVE cte AS (
SELECT order_product_id, order_id, product_id, model, quantity
FROM view_order_items
UNION ALL
SELECT cte.order_product_id, cte.order_id, cte.product_id, cte.model, cte.quantity - 1
FROM cte INNER JOIN view_order_items
ON cte.order_product_id = view_order_items.order_product_id
WHERE cte.quentity > 1
)
SELECT * FROM cte
If you are running an older version, upgrade it.
I'm trying to break up a SQL table that needs to take a users name and find the unique user ID's from up to 4 systems.
The data is currently like this:
| Name | User_ID |
-----------------
| A | 10 |
| A | 110 |
| A | 1500 |
| A | 4 |
| B | 20 |
| B | 100 |
| B | 2 |
| C | 10 |
I need to pivot it around the user's name to look like this (the id's don't need to be in numerical order as the SYS#_ID for each doesn't matter):
| Name | SYS1_ID | SYS2_ID | SYS3_ID | SYS4_ID |
------------------------------------------------
| A | 4 | 10 | 110 | 1500 |
| B | 2 | 20 | 100 | NULL |
| C | 10 | NULL | NULL | NULL |
This is the code I have tried on MySQL:
PIVOT(
COUNT(User_ID)
FOR Name
IN (SYS1_ID, SYS2_ID, SYS3_ID, SYS4_ID)
)
AS PivotedUsers
ORDER BY PivotedUsers.User_Name;
I'm unsure if PIVOT works on MySQL as I keep getting an error "PIVOT unknown". Is there a way to find the values that each user has and if they do not appear in the table already add them to the next column with a max of 4 values?
In my access database, we keep track of two sets of dates. One set is for date of membership dues payments, the other set is date of other contributions (a non-membership donation.) There are multiple dates for each person depending on number of payments made for each type.
Example:
+----+---------------+---------------+
| ID | Dues_Date | Cont_Date |
+----+---------------+---------------+
| 1 | 01/01/15 | 09/12/11 |
| | 01/01/14 | |
| | 01/01/13 | |
| 2 | 07/30/14 | 06/20/13 |
| | | 11/12/11 |
+----+---------------+---------------+
First I needed to know the most recent payment for each of the two fields so I ran a query that tells me the MAX (most recent) date for each field.
Example Query:
+----+---------------+---------------+
| ID | Max Dues_Date | Max Cont_Date |
+----+---------------+---------------+
| 1 | 01/01/15 | 09/12/11 |
| 2 | 07/30/14 | 06/20/13 |
| 3 | 02/11/13 | 09/16/14 |
| 4 | 07/30/12 | 06/20/11 |
| 5 | 12/13/13 | 11/12/14 |
+----+---------------+---------------+
Now I need a third field in the same query to compare the results of the first two fields and show which is the MAX of those two.
I have column 2 and 3 in the query; how can I take that and create column 4 in the same query?
Example Query:
+----+---------------+---------------+-----------------+
| ID | Max Dues_Date | Max Cont_Date | Max Date(DD&CD) |
+----+---------------+---------------+-----------------+
| 1 | 01/01/15 | 09/12/11 | 01/01/15 |
| 2 | 07/30/14 | 06/20/13 | 07/30/14 |
| 3 | 02/11/13 | 09/16/14 | 09/16/14 |
| 4 | 07/30/12 | 06/20/11 | 07/30/12 |
| 5 | 12/13/13 | 11/12/14 | 11/12/14 |
+----+---------------+---------------+-----------------+
Try adapting this to your own scenario:
SELECT tblTest.DueDate, tblTest.ContDate, [DueDate]-[ContDate] AS Test, IIf([Test]<0,[ContDate],[DueDate]) AS MaxRes
FROM tblTest;
"Test" finds which is the later date, ContDate or Due Date. The IIf statement selects the later date.
Does this help?