I am trying to use the following MySQL query:
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline AS l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
WHERE l.account_no = 32049 OR l.account_no IS NULL
However this is returning no rows, as there are no account_no rows in last_24_topline that match. From all that I understand and have read this query should still return all the rows from top_lines, even though no rows match in last_24_topline since I am checking for a value or null, but it is not. Are there any options or settings in MySQL (5.7.2) that would cause this behavior?
Just for information, this query works as expected:
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
AND l.`account_no` = 32049
I'm unable to use this construct however since I am using entity framework and you can only pass columns in and not values to the joins
CREATE TABLE `last_24_topline` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`member_no` varchar(30) NOT NULL,
`branch_no` int(11) DEFAULT NULL,
`employee_no` varchar(25) DEFAULT NULL,
`account_no` varchar(25) DEFAULT NULL,
`salesperson_name` varchar(255) DEFAULT NULL,
`customer_name` varchar(255) DEFAULT NULL,
`mfg` varchar(5) DEFAULT NULL,
`mfg_description` varchar(255) DEFAULT NULL,
`last_three` decimal(10,2) DEFAULT '0.00',
`last_twelve` decimal(10,2) DEFAULT '0.00',
`ly_last_three` decimal(10,2) DEFAULT '0.00',
`ly_last_twelve` decimal(10,2) DEFAULT '0.00',
PRIMARY KEY (`id`),
KEY `ix_branch_no` (`branch_no`),
KEY `ix_employee_no` (`employee_no`),
KEY `ix_member_line_account` (`member_no`,`mfg`,`account_no`),
KEY `ix_member_line` (`member_no`,`mfg`),
KEY `ix_account_no` (`account_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `top_lines` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`member_no` varchar(30) NOT NULL,
`line_no` varchar(5) NOT NULL,
`line_description` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_line_no` (`member_no`,`line_no`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=latin1
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (1,'520','772','FED ROTOR/DRUM');
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (2,'520','952','FED SST CERAMIC');
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (3,'520','954','FED SST FRICTION');
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (4,'520','162','EVS FRICTION');
INSERT INTO `last_24_topline` (`id`, `member_no`, `branch_no`, `employee_no`, `account_no`, `salesperson_name`, `customer_name`, `mfg`, `mfg_description`, `last_three`, `last_twelve`, `ly_last_three`, `ly_last_twelve`) VALUES('1','520','0','10856','463854','FORD, JAMES,','JIFFY LUBE','459','FEDERATED AIR FILTER','0.00','15.21','0.00','0.00');
INSERT INTO `last_24_topline` (`id`, `member_no`, `branch_no`, `employee_no`, `account_no`, `salesperson_name`, `customer_name`, `mfg`, `mfg_description`, `last_three`, `last_twelve`, `ly_last_three`, `ly_last_twelve`) VALUES('2','520','0','10856','463854','FORD, JAMES,','JIFFY LUBE','460','FILTERS','0.00','0.00','0.00','16.48');
INSERT INTO `last_24_topline` (`id`, `member_no`, `branch_no`, `employee_no`, `account_no`, `salesperson_name`, `customer_name`, `mfg`, `mfg_description`, `last_three`, `last_twelve`, `ly_last_three`, `ly_last_twelve`) VALUES('3','520','0','10856','463854','FORD, JAMES,','JIFFY LUBE','863','SMP T SERIES','0.00','0.00','0.00','50.67');
I would expect, even with no data in last_24_topline that matches, for the first query to produce a result set containing all the rows in top_lines with null values for the columns from last_24_topline.
Expected results:
So, creating the same schema into another database and inserting only the example data I provided above, I get the results I expect. I am testing further with copying the full rows to the second database to see if it still gives the expected results.
update
Copying all data into the new tables causes the problem to resurface. I'm trying to pare down to the minimum necessary to replicate the issue.
Try detecting for empty string too, maybe the fields are not NULL, but empty strings.
SELECT *
FROM
top_lines t
LEFT JOIN
last_24_topline AS l ON l.member_no = t.member_no AND l.mfg = t.line_no
WHERE
(l.account_no = '' OR l.account_no = '32049' OR l.account_no IS NULL)
If you want more help, i will need a sample data for "table last_24_topline" and the expected output after the join.
As a second try, you can use this one:
SELECT *
FROM
top_lines t
LEFT JOIN
last_24_topline AS l ON l.member_no = t.member_no AND l.mfg = t.line_no
WHERE
l.id IS NULL
OR
(l.id IS NOT NULL AND l.account_no = '32049')
Use a column involved in the join instead of l.account_no this way rows from top_lines will be returned if there is no matching row in the left table.
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline AS l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
WHERE l.account_no = 32049 OR l.`member_no` IS NULL
Alternatively place the account number filter directly in to the join
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline AS l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
AND l.account_no = 32049
On the query without the account number in the join, the join does match row in the last_24_toplines table, but it does not match the account number in the where clause, so it is filtered out and not seen as a row from top_lines without a matching row from last_24_topline.
So, for example this row from the top_line table
Will match this row from the last_24_toplines
but both will then be filtered out, because the account_no didn't match what was in the where clause: WHERE l.account_no = 32049 OR l.account_no IS NULL
The query with the check for account_no within the join will still match the row from top_line, but will not have a matching row from last_24_topline, so you will get a row with top_lines data with null last_24_topline.
I use the following query:
select *
from TEST2 t1 join TEST2 t2
where t1.TID <> t2.TID
and t1.ST = t2.ST
and t1.SAL > t2.SAL
and t1.TR < t2.TR;
I have 16 attributes in my table. But when i fire the above query i get result of two rows combined in one row with 32 attributes.
I want to get the result as two different rows and not one row, i.e the combination of both in one row.
6|Mark|Murro|M|970|-3134|Denver|CO|80251|S|Y|70000|4|0|0|0|0
2|Chunho|Black|M|719|-4662|Denver|CO|80290|M|N|60000|5|0|0|0
As shown above, both the rows get combined and comes as
6|Mark|Murro|M|970|-3134|Denver|CO|80251|S|Y|70000|4|0|0|0|0|2|Chunho|Black|M|719|-4662|Denver|CO|80290|M|N|60000|5|0|0|0
Table Schema :
CREATE TABLE `TEST2` (
`TID` int(11) DEFAULT NULL,
`FN` text,
`LN` text,
`GD` text,
`AC` int(11) DEFAULT NULL,
`PH` text,
`CT` text,
`ST` text,
`ZIP` int(11) DEFAULT NULL,
`MS` text,
`CH` text,
`SAL` int(11) DEFAULT NULL,
`TR` int(11) DEFAULT NULL,
`STX` int(11) DEFAULT NULL,
`MTX` int(11) DEFAULT NULL,
`CTX` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
But i want them seperate
Please help me out
It is a little unclear what you are really trying to do, but the following should implement your logic
select t.*
from test2 t
where exists (select 1
from test2 t2
where t.tid <> t2.tid and t.st = t2.st and t.sal > t2.sal and t.tr < t2.tr
) or
exists (select 1
from test2 t2
where t.tid <> t2.tid and t.st = t2.st and t.sal < t2.sal and t.tr > t2.tr
);
Because you want both rows, it needs to check for the conditions in both directions.
I would like to be able to set default values for home_country field using update statement.
This is by database table:
CREATE TABLE `countries` (
`id` smallint(6) NOT NULL AUTO_INCREMENT,
`name` varchar(70) COLLATE utf8_unicode_ci NOT NULL,
`home_country` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
) ENGINE=MyISAM;
I'm using :
$sql = "UPDATE countries SET home_country = DEFAULT WHERE id = 1"
But for some reason it's not working for me.
In the above Country, with ID 1 should have home_country value set to 1, while all other reset to 0
You are better off just running the value directly
UPDATE countries SET home_country = 0 WHERE id = 1;
If you want the default value dynamically set, you'll have to do something insane like this
UPDATE countries SET home_country =
(SELECT column_default FROM information_schema.columns
WHERE table_schema=DATABASE()
AND table_name ='countries'
AND column_name = 'home_country') WHERE id = 1;
You may use the function DEFAULT() instead.
$sql = "UPDATE countries SET home_country = DEFAULT(home_country) WHERE id = 1"
https://www.geeksforgeeks.org/mysql-default-function/
I have table of link
CREATE TABLE `linktable` (
`id ` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`idParent` BIGINT(20) UNSIGNED NOT NULL,
`Role` ENUM('Contacts','Expert','...') NULL DEFAULT NULL,
`idChild` BIGINT(20) UNSIGNED NOT NULL,
PRIMARY KEY (`idt`),
UNIQUE INDEX `UK_Parent_Child_Role` (`idParent`, `idChild`, `Role`)
)
I want to update this table and don’t break the unique key.
With other database I make something like this :
Update linktable lt1 Set lt1.Parent = :ziNew Where lt1.idParent = :ziOld
and not exists (select * from linktable lt2 where lt2.idParent = :ziNew and lt1.role = lt2.role and lt1.idChild = lt2.idChild);
How to make this with MySQL ?
Using your same syntax for variables, you would do this with a join:
Update linktable lt1 left outer join
(select *
from linktable lt2
where lt2.idParent = :ziNew
) lt2
on lt1.role = lt2.role and lt1.idChild = lt2.idChild
Set lt1.Parent = :ziNew
Where lt1.Parent =:ziOld and lt2.idParent is null;
The problem in MySQL is that the subquery is one the same table as the updated table. If it were a different table, then the original form with not exists would still work.
So this is my query:
SELECT SQL_CALC_FOUND_ROWS wagons.id,
wagons.mid,
wagons.year,
wagons.make,
wagons.model,
wagons.nickname,
wagons.description,
members.first,
members.last,
wagon_photos.filename,
Count(DISTINCT( likes.id )) AS likes,
Count(DISTINCT( comments.id )) AS comments
FROM wagons
INNER JOIN members
ON members.mid = wagons.mid
LEFT JOIN wagon_photos
ON wagon_photos.wid = wagons.id
LEFT JOIN likes
ON likes.wid = wagons.id
LEFT JOIN comments
ON comments.wid = wagons.id
GROUP BY wagons.id
ORDER BY wagons.id DESC
LIMIT 10
I am trying to fetch the wagon_photos.filename where wagon_photos.default is the maximum value. (It's a boolean, where only one row (for each wagon_photos.wid) will be 1.) On the off-chance the member does not have a default photo selected, I'd like it to return the lowest wagon_photos.id if possible.
I have tried numerous queries with ORDER BY and GROUP BY, but I think it may be a little more complicated than that. If I use a WHERE clause, it left out any wagons that did not have any photos linked to it, which I do not want to do.
CREATE TABLE `wagons` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`mid` int(8) DEFAULT NULL,
`year` varchar(4) DEFAULT NULL,
`make` varchar(50) DEFAULT NULL,
`model` varchar(100) DEFAULT NULL,
`nickname` varchar(200) DEFAULT NULL,
`description` mediumtext,
`featured` int(1) DEFAULT '0',
`visibility` int(1) DEFAULT '1',
`commision` int(1) DEFAULT '1',
`feat1title` varchar(50) DEFAULT NULL,
`feat2title` varchar(50) DEFAULT NULL,
`feat3title` varchar(50) DEFAULT NULL,
`feat4title` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=617 DEFAULT CHARSET=utf8;
CREATE TABLE `wagon_photos` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`wid` int(11) DEFAULT NULL,
`filename` varchar(255) DEFAULT NULL,
`caption` varchar(255) DEFAULT '',
`default` int(1) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8;
Let me try and understand what you're asking. I think what you're asking is "how do I construct a query where I want to select all of the items that have the max value of a particular column". If that's the case, you want to break this down into simpler units in order to solve it. First, you'll need the max value itself:
select max(wp.default) as max_val from wagon_photos wp
This gets you the max value.
Next you can create a query to select rows where a condition is true, but leave the condition out for a moment:
select (your rows) from wagons w where (a condition will go here)
And your condition is that you want wagon_photos.default to equal the max value. So you'll need to join in that table:
select (your rows) from wagons w join wagon_photos wp
on wp.wid = w.id where wp.default = (something)
Your "something" happens to be that max_value that we created a query for in the beginning. So putting this together, you'll use a subquery which will look like this:
select (your rows) from wagons w join wagon_photos wp
on wp.wid = w.id where wp.default = (
select max(wpb.default) from wagon_photos wpb
)
I haven't set up the tables myself to run this, so I might have goofed on parentheses, and it doesn't include all your joins. But I think this should point you in the right direction.
Well I feel a little bit silly now.
I finally thought of adding AND wagon_photos.default = 1 after the LEFT JOIN for wagon_photos and it works. I just need to make sure they always have a default setup, so I ran a script that on every update to their photos, it checks for a default, and if one isn't set, set the newest upload as default.
... LEFT JOIN wagon_photos ON wagon_photos.wid = wagons.id AND wagon_photos.default = 1 ...