SQL - trying to sum value from multiple reference - php

I have a problem to calculate sum of the amount column from some references field in 4 different tables. here is my tables :
First Table (Master) :
ID_1 | Name_1
1 A
2 B
Second table (Master) :
ID_2 | ID_1 | Name_2
1_1 1 A1
1_2 1 A2
2_1 2 B1
2_2 2 B2
Third Table (Transaction) :
ID_trans | ID_2 | trans_name | amount | cpy_ID
trans1 1_1 Rev 123 1400
trans2 2_1 Dir 321 1400
trans3 2_1 Ind 231 1400
trans4 1_2 OTH 234 1400
Fourth Table (report template) :
report_set_id | report_set_name | cpy_ID
set001 Own Apps 1400
set002 Third Party 1400
The main case is I have to create a report with the third table (transaction) as data reference. And the report template has been determined like this :
----------------------------------------------------
| 1 | 2 | TOTAL |------> (1 & 2 first table fields)
----------------------------------------------------
set001 | (data 1) | - | (horizontal sum)
set002 | - | (data 2) | (horizontal sum)
-----------------------------------------------------
TOTAL | (sum of 1)| (sum of 2) |
which is :
(data 1 & data 2) = summary data from transaction table with same ID_2 and put in the column 1 rows (bacause ID_1 is foreign key in the second table)
I know my language is complicated to understand cause actually its hard to explaining by words, but I hope you guys can get what exactly I mean it :D
Can someone give me some advice to solve my problem? Thanks

If this will only ever have 2 data columns (as labelled "1" and "2" in your example) then it will be quite easy to write in SQL and we could do that. But if there will be several data columns, and if there will be a variable number of data columns, then we are into the general "pivot table" question. You can find many discussions on this topic under the [pivot] tag in stackoverflow. My own opinion is that anything but trivial formatting (including almost all pivot tables) is best done in the application. Use SQL to group and aggregate the data, then use a visualisation tool, or your application, to format it. I have written more about this on my website, where I explain a couple of common approaches and why I don't use them.

Related

MySql db structure to store a list of items in sequence

I need to store and retrieve items of a course plan in sequence. I also need to be able to add or remove items at any point.
The data looks like this:
-- chapter 1
--- section 1
----- lesson a
----- lesson b
----- drill b
...
I need to be able to identify the sequence so that when the student completes lesson a, I know that he needs to move to lesson b. I also need to be able to insert items in the sequence, like say drill a, and of course now the student goes from lesson a to drill a instead of going to lesson b.
I understand relational databases are not intended for sequences. Originally, I thought about using a simple autoincrement column and use that to handle the sequence, but the insert requirement makes it unworkable.
I have seen this question and the first answer is interesting:
items table
item_id | item
1 | section 1
2 | lesson a
3 | lesson b
4 | drill a
sequence table
item_id | sequence
1 | 1
2 | 2
3 | 4
4 | 3
That way, I would keep adding items in the items table with whatever id and work out the sequence in the sequence table. The only problem with that system is that I need to change the sequence numbers for all items in the sequence table after an insertion. For instance, if I want to insert quiz a before drill a I need to update the sequence numbers.
Not a huge deal but the solutions seems a little overcomplicated. Is there an easier, smarter way to handle this?
Just relate records to the parent and use a sequence flag. You will still need to update all the records when you insert in the middle but I can't really think of a simple way around that without leaving yourself space to begin with.
items table:
id | name | parent_id | sequence
--------------------------------------
1 | chapter 1 | null | 1
2 | section 1 | 1 | 2
3 | lesson a | 2 | 3
4 | lesson b | 2 | 5
5 | drill a | 2 | 4
When you need to insert a record in the middle a query like this will work:
UPDATE items SET sequence=sequence+1 WHERE sequence > 3;
insert into items (name, parent_id, sequence) values('quiz a', 2, 4);
To select the data in order your query will look like:
select * from items order by sequence;

Get stored id's using iteration

I please need some help:
I have this database, which has this fields with their respect values:
agency_id | hostess_id
3 | 12-4-6
5 | 19-4-7
1 | 1
In hostess_id are stored all hostesses ids that are associated with that agency_id but separated with a "-"
Well, i login as a hostess, and i have the id=4
I need to retrieve all the agency_id which contain the id=4 , i can't do this with like operator.. i tried to do it by saving the hostess_id row to an array, then implode it, but i can't resolve it like this.
Please, please any idea?
You should change your database design. What you are describing is a typical N:N relation
Agencies:
agency_id | name
3 | Miami
5 | Annapolis
1 | New York
Hosteses
Hostes_id | name
4 | Helen
12 | May
19 | June
AgencyHostes
Hostes_id | agency_id
4 | 1
4 | 3
4 | 5
12 | 1
12 | 3
19 | 1
First, let me say that I absolutely agree with #JvdBerg on that this is terrible database design that needs to be normalized.
Let's think for a minute though, that you have no way of changing the database layout and that you must solve this with SQL, an inefficient but working solution would be
select agency_id from tablename where
hostess_id LIKE '4-%' OR
hostess_id LIKE '%-4-%' OR
hostess_id LIKE '%-4'
if you were searching for all agencies with hostess id 4. I build this on sqlfiddle to illustrate more thoroughly http://sqlfiddle.com/#!2/09a52/1
Mind though, that this SQL statement is hard to optimize since an index structure for substring matching is rarely employed. For very short id lists it will work okay though. If you have ANY chance at changing the table structure, normalize your schema like #JvdBerg suggested and look up database design and normal forms on google.

comparing values between different rows of database and getting maximum count

i have a table in which a row contains following data. So i need to compare data among themselves and show which data has maximum count.for ex. my table has following fruits name. So i need to compare these fruits among themselves and show max fruit count first.
s.no | field1 |
1 |apple,orange,pineapple |
2 |apple,pineapple,strawberry,grapes|
3 |apple,grapes, |
4 |orange,mango |
i.e apple comes first,grapes second,pineapple third and so on. and these datas are entered dynamically, so whatever the values is entered dynamically it needs to compare among themselves and get max count
Great question.
This is a classical bad outcome of not having the data normalized.
I recommend you to read about Database Normalization, normalize your tables and see after that how easy it is to do this with simple SQL queries
If you need to run queries on column field 1, then why not consider normalization ? Otherwise it might keep on getting complex and dirty in future.
Your current table will look like this (for serianl number 1 only), Pk can be an autoincrement primary key.
Pk | s.no |fruitId|
1 | 1 |1 |
2 | 1 |2 |
3 | 1 |3 |
Your New Table of Fruits
PK |fruitName |
1 |Apple |
2 |Orange |
3 |Pineapple |
This also helps you to avoid redundancy.
Quick solution would be counting the amount of fruits where you insert/update the row and add a fruitCount column. You can then use this column to order by.
Zohaib has to correct solution though - if you have the time and possibility for such changes. And I definitely suggest you to read Tudor's link!

(My)SQL Query to search for multiple values on multiple tables (some rows, some columns)

I am creating a search using MySQL & PHP on an existing table structure.
Multiple search keywords can be entered and the user can opt to either match ALL or ANY. The any form is not too difficult, but i am breaking my head on writing an efficient solution for the AND form.
The following is about the AND form, so all the search keywords must be found.
The 2 tables i have to work with (search in) have a structure as follows:
Table1
- item_id (non-unique)
- text
Table2
- item_id (unique)
- text_a
- text_b
- text_c
(The real solution will also have a 3rd table, but that is structure the same way as Table1. Table2 will have around 20 searchable columns)
Table1 can have multiple rows for each item_id with different text.
Consider having only 2 search keywords (can be more in real live), then both must exist in:
- both in a single row/column
or:
- in 2 different columns of maybe different tables.
or:
- in 2 different rows with the same item_id (in case of both keywords found in different rows of Table1)
All i could come up with are very intensive sub-queries but that would bring the server down or the response times would be huge.
As i am using PHP i could use intermediate queries and store the results for use in a later final query.
Anyone some good suggestions?
Edit: There where requests for real examples, so here it goes.
Consider the following 2 tables with data:
Table 1
+---------+-----------+-----------+-----------+-----------+
| item_id | t1_text_a | t1_text_b | t1_text_c | t1_text_d |
+---------+-----------+-----------+-----------+-----------+
| 1 | aaa bbb | NULL | ccc | ddd |
| 2 | aaa ccc | ddd | fff | ggg |
| 3 | bbb | NULL | NULL | NULL |
+---------+-----------+-----------+-----------+-----------+
Table2
+---------+----------+---------+
| item_id | sequence | t2_text |
+---------+----------+---------+
| 1 | 1 | kkk lll |
| 2 | 1 | kkk |
| 2 | 2 | lll |
| 3 | 1 | mmm |
+---------+----------+---------+
PS In the real database (which i can not change, so full text indexes or changes to table definition are not an option) Table1 has about 20 searchable columns and there are 2 tables like Table2. This should not make a difference to the solution, although it is something to consider from a performance perspective.
Example searches:
Keywords: aaa bbb
Should return:
- item_id=1. Both keywords are found in column t1_text_a.
Keywords: ccc ddd
Should return:
- item_id=1. "ccc" is found in t1_text_c, "ddd" is found in t1_text_d.
- item_id=2. "ccc" is found in t1_text_a, "ddd" is found in t1_text_b.
Keywords: kkk lll
Should return:
- item_id=1. Both keywords found in a single row of Table2 in column t2_text.
- item_id=2. Both keywords found in Table2, but in separate rows with the same item_id.
Keywords: bbb mmm
Should return:
- item_id=3. "bbb" is found in table1.t1_text_a, "mmm" is found in table2.t2_text.
My progress so far
I actually, for now, gave up on trying to catch this in mostly SQL.
What i did do is to create a query for each table retrieving any row that matches at least 1 of the search keywords. If there is only 1 search keyword the query uses a LIKE, otherwise a REGEXP 'keyword1|keyword2'.
These rows are put in a PHP array with the item_id as the index, and a concatenation of all the strings (searchable columns) as value. When finished retrieving all possible rows, i search the array for rows that match all keywords in the concatenated field.
Most likely not the best solution and it will not scale very well if the search will return many candidate rows with at least 1 match.
It's hard to provide you with a finite answer since you do not give a lot of details about your case.
But maybe this can give you a starting point:
SELECT * FROM table1 AS tbl1
INNER JOIN table2 AS tbl2
WHERE
tbl1.text LIKE %search_word1%
AND tbl1.text LIKE %search_word2%
AND tbl2.text_a LIKE %search_word1%
AND tbl2.text_a LIKE %search_word2%
AND tbl2.text_b LIKE %search_word1%
AND tbl2.text_b LIKE %search_word2%
AND tbl2.text_c LIKE %search_word1%
AND tbl2.text_c LIKE %search_word2%
You can adapt with JOIN, INNER JOIN, LEFT JOIN, RIGHT JOIN and the different LIKE and AND/OR statements to obtain the result you're looking for.
Google some join examples with LIKE statements for more details.
But as Tom H. said, it'd be better if you could post a more precise table structure and a real exemple of search terms...

How do I track changes and store calculated content in Nermalization?

I'm trying to create a table like this:
lives_with_owner_no from until under_the_name
1 1998 2002 1
3 2002 NULL 1
2 1997 NULL 2
3 1850 NULL 3
3 1999 NULL 4
2 2002 2002 4
3 2002 NULL 5
It's the Nermalization example, which I guess is pretty popular.
Anyway, I think I am just supposed to set up a dependency within MySQL for the from pending a change to the lives_with table or the cat_name table, and then set up a dependency between the until and from column. I figure the owner might want to come and update the cat's info, though, and override the 'from' column, so I have to use PHP? Is there any special way I should do the time stamp on the override (for example, $date = date("Y-m-d H:i:s");)? How do I set up the dependency within MySQL?
I also have a column that can be generated by adding other columns together. I guess using the cat example, it would look like:
combined_family_age family_name
75 Alley
230 Koneko
132 Furrdenand
1,004 Whiskers
Should I add via PHP and then input the values with a query, or should I use MySQL to manage the addition? Should I use a special engine for this, like MemoryAll?
I disagree with the nermalization example on two counts.
There is no cat entity in the end. Instead, there is a relation (cat_name_no, cat_name), which in your example has the immediate consequence that you can't tell how many cats named Lara exist. This is an anomaly that can easily be avoided.
The table crams two relations, lives_with_owner and under_the_name into one table. That's not a good idea, especially if the data is temporal, as it creates all kinds of nasty anomalies. Instead, you should use a table for each.
I would design this database as follows:
create table owner (id integer not null primary key, name varchar(255));
create table cat (id integer not null primary key, current_name varchar(255));
create table cat_lives_with (
cat_id integer references cat(id),
owner_id integer references owner(id),
valid_from date,
valid_to date);
create table cat_has_name (
cat_id integer references cat(id),
name varchar(255),
valid_from date,
valid_to date);
So you would have data like:
id | name
1 | Andrea
2 | Sarah
3 | Louise
id | current_name
1 | Ada
2 | Shelley
cat_id | owner_id | valid_from | valid_to
1 | 1 | 1998-02-15 | 2002-08-11
1 | 3 | 2002-08-12 | 9999-12-31
2 | 2 | 2002-01-08 | 2001-10-23
2 | 3 | 2002-10-24 | 9999-12-31
cat_id | name | valid_from | valid_to
1 | Ada | 1998-02-15 | 9999-12-31
2 | Shelley | 2002-01-08 | 2001-10-23
2 | Callisto | 2002-10-24 | 9999-12-31
I would use a finer grained date type than just year (in the nermalization example having 2002-2002 as a range can really lead to messy query syntax), so that you can ask queries like select cat_id from owner where '2000-06-02' between valid_from and valid_to.
As for the question of how to deal with temporal data in the general case: there's an excellent book on the subject, "Developing Time-Oriented Database Applications in SQL" by Richard Snodgrass (free full-text PDF distributed by Richard Snodgrass), which i believe can even be legally downloaded as pdf, Google will help you with that.
Your other question: you can handle the combined_family_age either in sql externally, or, if that column is needed often, with a view. You shouldn't manage the content manually though, let the database calculate that for you.

Categories