How to select database query in this case? - php

Hi I am running into a unique problem. I have database structure of sales order and comparision tables like below.
enter image description here
There will be more records in comparision table.
Basically I want to get the result like the pictures belows. Note: the AFFID can be any random number.
I haven't be able to think of a good way to call SQL. I feel like I have to call SQL then create a new Array that has structure
[
'campaign_left',
'campaign_right'
'Comparision_id'
]
to be able to achieve this.

I think I can get the answer by doing this :
step 1 : get the uniqueAFFIDS array = [1020,1040,1028]
step 2 : sort the uniqueAFFIDS array = [ 1020,1028,1040]
ForEach Comparisions as Comparision
------ ForEach uniqueAFFIDS as uniqueAFFID
------------- $total left = Select Where campaign_id = comparision->campaign_id-left && affid = uniqueAFFID ;
------------- $total right = Select Where campaign_id = comparision->campaign_id-right && affid = uniqueAFFID ;
Then i just display it.
I wonder if anyone has good idea other that this.
Thanks.

Related

How to group by aggregation of column in foreign table with many-to-many relation in Eloquent?

I am starting to get headaches over this so I thought I just post it here.
I have two tables that are related through a pivot table (as it is a many-to-many relationship). I use Laravel and Eloquent (but general help on how to achieve this with normal SQL queries is also highly appreciated).
I want to order the first table based a column of the second one but the column needs to be "aggregated" for this.
Example with Cars that are shared by many drivers and can have different colors:
Car-Table: [id, color]
Driver-Table: [id, name]
Car.Driver-Table: [car_id, driver_id]
I need a query that gets all drivers that only drive red cars and then all that don't drive red cars.
I have to use a query because I'll maybe do other things (like filtering) on this query afterwards and want to paginate in the end.
I already use queries that get either one of the two groups. They look like this:
In the Driver model:
public function redCars() {
return $this->cars()->where('color', 'red');
}
public function otherColoredCars() {
return $this->cars()->where('color', '<>', 'red');
}
And then in somewhere in a controller:
$driversWithOnlyRedCars = Driver::whereDoesntHave('otherColoredCars')->get();
$driversWithoutRedCars = Driver::whereDoesntHave('redCars')->get();
Is there a way to combine these two?
Maybe I am just thinking completely wrong here.
Update for clarification:
Basically I would need something like this (ot any other way that would lead to the same outcome)
$driversWithOnlyRedCars->addTemporaryColumn('order_column', 0); // Create temporary column with value 0
$driversWithoutRedCars->addTemporaryColumn('order_column', 1);
$combinedQuery = $driversWithOnlyRedCars->combineWith($driversWithoutRedCars); // Somehow combine both queries
$orderedQuery = $combinedQuery->orderBy('order_colum');
$results = $combinedQuery->get();
Update 2
I think, I found out how to get near my goal with raw queries.
Would be something like this:
$a = DB::table(DB::raw("(
SELECT id, 0 as ordering
FROM drivers
WHERE EXISTS (
SELECT * FROM cars
LEFT JOIN driver_car ON car.id = driver_car.car_id
WHERE driver.id = driver_car.driver_id
AND cars.color = 'red'
)
) as only_red_cars"));
$b = DB::table(DB::raw("(
SELECT id, 1 as ordering
FROM drivers
WHERE EXISTS (
SELECT * FROM cars
LEFT JOIN driver_car ON car.id = driver_car.car_id
WHERE driver.id = driver_car.driver_id
AND cars.color <> 'red'
)
) as no_red_cars"));
$orderedQuery = $a->union($b)->orderBy('ordering');
Now the problem is that I need the models ordered like this and paginated in the end so this is not really an answer to my question. I tried to convert this back to models but I didn't succeed yet. What I tried:
$queriedIds = array_column($orderedQuery->get()->toArray(), 'id');
$orderedModels = Driver::orderByRaw('(FIND_IN_SET(drivers.id, "' . implode(',', $queriedIds) . '"))');
But looks like FIND_IN_SET only allows for a column of the table as second parameter. Is there another way to get the Models in the right order out of the ordered union query?
You can use a UNION query:
$driversWithOnlyRedCars = Driver::select('*', DB::raw('0 as ordering'))
->whereDoesntHave('otherColoredCars');
$driversWithoutRedCars = Driver::select('*', DB::raw('1 as ordering'))
->whereDoesntHave('redCars');
$drivers = $driversWithOnlyRedCars->union($driversWithoutRedCars)
->orderBy('ordering')
->orderBy('') // TODO
->paginate();
How do you want drivers with the same ordering to be ordered? You should add a second ORDER BY clause to get a consistent order every time you execute the query.
This is the best I got:
$driversWithOnlyRedCars = Driver::whereHas('cars',function($q){
$q->where('color', 'red');
})->withCount('cars')->get()->where('cars_count',1);

How to go over comma separted values in MYSQL

My database structure is like this:
Movie Name GenreID**
Movie1 1,2,3
Movie2 2,4
Movie3 4,5,16
I need to select a Movie name based on the Genre ID the user selected which I put inside the genreIDArray[]
Let's say for example the genreIDArray has values: $genreIDArray = ['1','2','3'];
My current query method is the ff:
Here I prepared each ID into parts so the result won't become genreID LIKE (%1,2,3%) because I checked this doesn't work.
So I did this separation loop:
$queryParts = array();
foreach($genresIDArray as $genreID) {
$queryParts[] = "'%".$genreID."%'";
}
After the separation loop I put together the final query:
$genreString = implode(" OR genreID LIKE ",$queryParts);
$genreQuery = " SELECT * FROM movies WHERE (genreID LIKE {$genreString}) ";
gave me this final query output:
SELECT * FROM movies WHERE (genreID LIKE '%1%' OR genreID LIKE '%2%' OR genreID LIKE '%3%')
This actually works, but apparently not that efficient because genreID 11,12,13 and so on that start with 1 is also selected. I think I'm missing the MYSQL LIKE logic here. I've tried '%$genreID' which means to select the starting or first number/letter of a table data, but that's still the same thing, $genreID% doesn't and would not work because this only means genreid ENDING letters/number will be selected.
I hope I spelled that out clear enough. I'm in a bind here. Please help.
Thank you so much.
There is a very cool function for that. You can use FIND_IN_SET.
SELECT * FROM test WHERE FIND_IN_SET(1,colors)
But if its possible you should avoid such structures in your database and normalize your database.

How to count if value of a variable is repeated?

I am learning how to work with MySQL, and at the moment I succeed to show data from my table, using:
while($objResult2 = mysqli_fetch_assoc($objQuery_product)) {
Results are shown by using this variable $objResult2["id_product"]; this way i can take from DB any field I want like: $objResult2["name"]; $objResult2["email"]; etc.
But what i do if i have in the table more rows with the same id_product?
I want to write a if statment, which counts if id_product repeats. How to do that? If it is a lot of work, atleast please give me an idea of the right tutorial that I must read. Because i am trying second day to fix this, and searched google but i didnt find what i need, or maybe i coulndt understand it....
This is my query
$sql_product = "SELECT * FROM ps_product AS prod";
$join_product = " LEFT JOIN ps_product_lang AS lang ON lang.id_product = prod.id_product";
$join2_product = " LEFT JOIN ps_stock_available AS stok ON stok.id_product = prod.id_product";
$where_product =" WHERE prod.id_category_default = $idp AND lang.id_lang = 8";
$sql_product = $sql_product.$join_product.$join2_product.$where_product;
$objQuery_product = mysqli_query($objConnect, $sql_product) or die ("Error Query [".$sql_product."]");
You can simple remove the same id_product using DISTINCT keyword in your query. Such as:
SELECT DISTINCT id_product FROM my_table
This will give you results with different ids only.
The second way of doing it is taking the output values inside an array.
In your while loop:
$my_array[] = $objResult2["id_product"];
Then using array_filter remove all the duplicates inside the array.
YOu can also use array_count_values() if you want to count the duplicate values.
Ok here we go. For example you are fetching data with this query.
select id_product, name from PRODUCTS;
Suppose above query gives you 5 records.
id_product name
1 bat
2 hockey
2 hockey
3 shoes
4 gloves
Now you got 2,2 and hockey, hockey. Instead of thinking this way that you have to introduce an if statement to filter repeating records or same name or id_product records.
Rewrite your sql query like this.
select distinct id_product, name from PRODUCTS;
Or if you need count of each then my friend you will write your query something like this...
Graham Ritchie, if Andrei needs count of each repeating record then we will do something like this in our query.
SELECT PRODUCT_ID,
COUNT(PRODUCT_ID) AS Num_Of_Occurrences
FROM PRODUCTS
GROUP BY PRODUCT_ID
HAVING ( COUNT(PRODUCT_ID) > 1 );
SELECT id_product,COUNT(*) AS count
FROM tablename
GROUP BY id_product;
This query will then return you two items in your query
$objResult2["id_product"] //and
$objResult2["count"]
The if statement is then just
if($objResult2["count"] > 1){
//Do whatever you want to do with items with more than 1 occurence.
//for this example we will echo out all of the `product_id` that occur more than once.
echo $objResult2["id_product"] . " occurs more than once in the database<br/>";
}

I want to get output result from second table based on first table rows output in json-php

I have knowledge of PHP but I am still learning Json. First of all I want to clear what I am looking for. I have two tables in mysql database, table1(users) and table2(business). Table "users" contains these rows(id, uid, business_name) and table "business" contains these rows(id, uid, category).
I have following code in PHP page:
if(isset($_GET['catName'])) {
$cat = $_GET['catName'];
$stmt = $pdo->prepare("SELECT id, uid, category FROM business WHERE category = ? ");
$stmt->execute(array($_GET['catName']));
$arr = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
I am able to get json output on my html page e.g.
101, 102, 103 and so on.
But I want to get business_name rows like ABC Business, XYZ Business, 123 Business and so on from second table "business" based on the output uid from first table. In brief, I want business_name output instead of uid output from second table.
Please help me. Thank you so much in advance.
You have an associative array, with the results from the query. It sounds like you want the business names, but you are not querying for them.
So the first step would be fix your broken query!
It's difficult to tell what you want from the query, but you're mixing the users table with the business table, so I'm guessing you really want business names based on users.
SELECT b.business_name FROM users u JOIN business b ON u.uid = b.uid WHERE category = ?
Then, you have to access your $arr variable correctly to get the business names
foreach ($arr as $bus_sql_result) {
echo $bus_sql_result['business_name']."\n";
}
This is not in JSON format, I'm not sure what JSON has to do with what you want, but if you really want it that way, you could try something like
$business_names = array();
foreach ($arr as $bus_sql_result) {
$business_names[] = $bus_sql_result['business_name'];
}
echo json_encode($business_names);
Thank you so much Chris and Jormundir. Joining the both tables really solved my problem. This is what I have done:
$stmt = $pdo->prepare("SELECT business.uid, users.business_name FROM business,users WHERE business.uid = users.uid AND business.category= ? ");
In html page I have put "business_name" array instead of "uid" and I have got result whatever I was looking for.
Thanks you so much all of you.

Create and optimize mysql query, php

Having trouble to create quality and optimize mysql query.
Lets create a table with values.
CREATE TABLE flow
(
US1 varchar(20),
US2 varchar(30)
);
INSERT INTO flow
(US1, US2)
VALUES
('rasim', 'tere1'),
('rasim', 'tere2'),
('rasim', 'tere3'),
('rasim', 'tere4'),
('tere1', 'tere5'),
('tere1', 'tere6'),
('tere2', 'tere7'),
('tere3', 'tere8'),
('tere3', 'tere9'),
('tere4', 'tere10'),
('tere5', 'tere11'),
('tere5', 'tere12'),
('tere9', 'tere13'),
('tere9', 'tere14');
What i am trying to achieve:
$firstUs = DB::query("SELECT US2 FROM `flow` WHERE US1='rasim'");
while($first = DB::fetch($firstUs)):
$second =(int) // select and count(US2) foreach value where US1 = $first['US2'];
$third =(int) //select and count(US2) foreach value where US1 = $second['US2'];
$four = (int) //select and count(US2) foreach value where US1 = $third['US2'];
endwhile;
$firstUs = returns 4 values ( tere1, tere2, tere3, tere4 ). I whant the script to count for each of these values, the number of entries from US1. $second = returns 2 values ( tere5, tere6 ). Count value would be (2) on first php while loop.
How to create a good mysql script so that this will work and if there would be a lot of users accsesing this page, the server wont crash and speed of the query would be much less.
Thank you
I am traying to achieve a pyramid scheme. Where 'rasim' is the primary user name. Where $second , $third and $four is a int number of users per level. $second will have caount of all users in the second level of the pyramid.
Example image how it will look like. http://silverstream.ee/img/stack.PNG
I think the best option here would be to break the data out into separate tables so that you don't have the Primary Key (US1) be relational to the "Foreign Key" (US2) within the same table. Then you could accomplish what you are trying to do with a query as opposed to numerous loops.
Unfortunately I still have no idea what exactly you are trying to accomplish so it's impossible for me to create an example scenario with what you've given.
I think it's something like:
select f2.us1, count(f2.us2)
from flow f1
inner join flow f2
f1.us2=f2.us1
where f1.us1='rasim'
group by f2.us1
I hope this is what you want.

Categories