Mysql nested subquery - c#

I have a page that I'm trying to spice up a bit..
Basically my current SQL select is generated randomly from options chosen on a page.
However, I'd like the default sort order to be random; but from what I've read, I should avoid both nested subqueries in MySql, and order by rand.
But, what if I order by rand the limited number of records returned (less than 50?) with a nested subquery.
Is this a bad idea? And would this be a problem with a larger table of say 2kk + rows?
Here's what I'm thinking of doing
select * from (
select a.*,b.*
from a
left join b on b.id=a.id
where a.isactive AND etc etc
order by a.id DESC // select say page 2 of 50 newest records
limit 50,50
) tblrand order by rand() // randomize the order of those 50 records
**EDIT***
changed the inner order by a.displayorder to order by a.id DESC to better reflect the situation since the default sort order (if none specified) is newest records (ie... id sorted desc order)
and added some comments
*** SOLVED ***** (however i'd still like to know how this would pan out.. ie. how bad would it be performancewise for mysql... tnx in advance)
tnx dbsman.. i was thinking of the problem in a different way.
at first i wanted totally random rows, which as i explained would be a pain in the butt... (i got mixed up in what i wanted to do myself :)
but i think i found a solution that works like a charm with my problem doing it in the application side
//code that gets **Dataset ds** goes here
var rand = new Random();
var result = ds.Tables[0].AsEnumerable().OrderBy(r => rand.Next());
lst.DataSource = result.CopyToDataTable();

Related

MVC Joining many 2 many tables and filling list based on result in c#

I am doing a school project and need help with this last problem I am having.
Currently I am trying to do a many 2 many join and then fill an IEnumerable list with the result - using linq and lambda.
The purpose is to show the compatible games along with every product.
My code as of now:
else
{
var result = (from g in db.Games
join gs in db.GameSize
on g.GameId equals gs.GameId
join s in db.Size
on gs.SizeId equals s.SizeId
join p in db.Product
on s.SizeId equals p.SizeId
select p.Size.Name);
games = db.Games
.Where(game => game.GameSize
.All(s => s.Size.Name == result.FirstOrDefault()));
}
My idea is to join through the tables and find the gameid who have a matching productid - and then add them to "games".
I am aware that this table design is horrible and that I am only getting the first result in the list with FirstOrDefault().
Does anyone have a suggestion or solution to help me? Thanks.
Please ask if I am not making any sense.
Essentially I just wan't to show the games linked to a size. My table looks like this:
--SIZE
insert into size values ('Large')
insert into size values ('Medium')
insert into size values ('Small')
--GAMES
insert into games values ('Magic The Gathering')
insert into games values ('Pokemon')
insert into games values ('Dead of Winter')
--GAMESIZE (RELATION GAMES AND SIZE) (SIZEID, GAMEID)
insert into gamesize values (1, 1)
insert into gamesize values (2, 2)
insert into gamesize values (2, 3)
First, you should really move on from the LINQ to SQL syntax. The EF syntax is much easier and readable. For example:
var result = db.Games.Include("GameSize.Size.Product").Select(m => m.Size.Name);
Second, All doesn't do what you seem to think it does. It returns a boolean: true if all the items match the condition, false if not. It's very unlikely that all your GameSizes have the same Size.Name. You might be looking for Any here.
Third, this whole thing seems counter-intuitive. You're getting all the games and selecting all the size names. Then using that list of size names, to select games that have those size names. In other words, you're doing an extra query to get the results you already had. Remove the select from the result and use that for games instead.
Long and short, if I'm understanding your code properly, you can reduce all of this to just one simple line:
games = db.Games.Include("GameSize.Size.Product");

mysql random records give a duplicate data

I am developing a website where records are not sequential, records are displayed randomly.
I use simple mysql random method to display random records by using rand() with limit where limit is parameterized to get next record one by one.
I am using asp.net mvc framework and mysql database.
Here is mysql query.
select distinct
lw.Lawyer_id,
lw.name,
StateName,
ct.city,
Date_of_registration,
lawyer_views,
fl.practice
from
registration lw
left join
states st ON st.Id = lw.State_Id
left join
city ct ON ct.id = lw.City_Id
left join
total_views lwv ON lwv.l_id = lw.L_id
left join
rsuper rsub ON rsub.l_id = lw.L_Id
left join
lfilter fl ON fl.L_Id = lw.L_Id
where
lw.City_Id = '577'
and rsub.special_id = 1
and lw.status = 'Active'
and lw.L_id != 1
and lw.service = 'Free'
order by rand()
limit start , pageSize
in this query pageSize is total number of record which is 18 and start variable is change according to parameter but default value is 0.
It gives 18 records randomly on ajax request but problem is that it gives some duplicate records.
please tell me how to prevent this or other better solution for it and i also try other alternatives of rand() function but it not helps me.
I used this tutorial for better improvements in random records.
https://www.warpconduit.net/2011/03/23/selecting-a-random-record-using-mysql-benchmark-results/
Look here: http://jan.kneschke.de/projects/mysql/order-by-rand/
There uncovered research about how do rand select. May be one of the solutions from there can solve your problem.
P.S. I can't make comments so write post but it should be in comments...
UPD: looked at MySQL select 10 random rows from 600K rows fast ...

Linq order by ascending sort by descending

Sorry for title, but i didn't know how to write it better. I will try in post.
When I am trying to get values from database using linq with orderby something strange happens. Let's look on 4 queries:
//1
var badAsc = new ConcurrentBag<int>((from x in se.produkts orderby x.numerProduktu select x.numerProduktu));
//2
var bagDesc = new ConcurrentBag<int>((from x in se.produkts orderby x.numerProduktu descending select x.numerProduktu));
//3
var listAsc = (from x in se.produkts orderby x.numerProduktu select x.numerProduktu).ToList();
//4
var listdesc = (from x in se.produkts orderby x.numerProduktu descending select x.numerProduktu).ToList();
We got 2 ConcurrentBags<int> and 2 List<int>. What I was expecting from this is that 1 and 3 will be the same and also 2 and 4 will be the same. Check what values i got:
Ascending sort for ConcurrentBag<int> is in fact descending. On Microsoft site we can read, that ConcurrentBag is good when sorting does not matters, but as we can see in bagDesc, sorting is kept. To show, that I don't have any strange things in database I also make two List<int> where sorting is kept as it should be.
Executing select * from produkt in my database gives me values sorted like listAsc and bagDesc.
Database is mssql 2014 and numerProduktu is primary key in this table.
Do anybody know what happened there?
See here.
The ConcurrentBag appears to be implemented as a stack rather than a
queue. That is, the last item added is the first item removed. I
wouldn't count on that, though.
So they are getting added in reverse order. However, order is not meant to be reliably consistent in ConcurrentBag, so it's not guaranteed to always behave that way, especially if accessed by multiple threads.
If you care about maintaining the original order of entry, then you probably want a ConcurrentQueue.

LINQ Join 2 Datatables and With SUM AND GROUP BY

I simply can not get this to work out at all, so any expert help would be very much appreciated.
I'm trying (as the subject suggests) to join 2 datatables on Zip Code, but return a table which grouped this by State and has a SUM() of sales.
Here's the latest version of my troubles:
var results =(
from a in dtList.AsEnumerable()
join b in dtListCoded.AsEnumerable()
on a.Field<string>("ZIP") equals b.Field<string>("zip")
group a by {a.Field<string>("StateCode")} into g
select new {
StateCode = a.Field<string>("StateCode"),
SumSales = b.Sum(b => b.Field<double>("SUMSales"))
});
I can join the 2 tables but its getting the result i need that seems to be the tricky bit. If need be I will just have to do 2 queries, but that just seems a bit backward.
Thanks in advance.
Two queries wouldn't be any slower (they should be brought together into a single SQL query upon execution), and would be a lot more readable, transparent during debugging and reusable. I'd recommend breaking it down.

Using Linq to SQL, how do I find min and max of a column in a table?

I want to find the fastest way to get the min and max of a column in a table with a single Linq to SQL roundtrip. So I know this would work in two roundtrips:
int min = MyTable.Min(row => row.FavoriteNumber);
int max = MyTable.Max(row => row.FavoriteNumber);
I know I can use group but I don't have a group by clause, I want to aggregate over the whole table! And I can't use the .Min without grouping first. I did try this:
from row in MyTable
group row by true into r
select new {
min = r.Min(z => z.FavoriteNumber),
max = r.Max(z => z.FavoriteNumber)
}
But that crazy group clause seems silly, and the SQL it makes is more complex than it needs to be.
So, is there any way to just get the correct SQL out?
EDIT: These guys failed too: Linq to SQL: how to aggregate without a group by? ... lame oversight by LINQ designers if there's really no answer.
EDIT 2: I looked at my own solution (with the nonsensical constant group by clause) in the SQL Server Management Studio execution plan analysis, and it looks to me like it is identical to the plan generated by:
SELECT MIN(FavoriteNumber), MAX(FavoriteNumber)
FROM MyTable
so unless someone can come up with a simpler-or-equally-as-good answer, I think I have to mark it as answered-by-myself. Thoughts?
As stated in the question, this method seems to actually generate optimal SQL code, so while it looks a bit squirrely in LINQ, it should be optimal performance-wise.
from row in MyTable
group row by true into r
select new {
min = r.Min(z => z.FavoriteNumber),
max = r.Max(z => z.FavoriteNumber)
}
I could find only this one which produces somewhat clean sql still not really effective comparing to select min(val), max(val) from table:
var r =
(from min in items.OrderBy(i => i.Value)
from max in items.OrderByDescending(i => i.Value)
select new {min, max}).First();
the sql is
SELECT TOP (1)
[t0].[Value],
[t1].[Value] AS [Value2]
FROM
[TestTable] AS [t0],
[TestTable] AS [t1]
ORDER BY
[t0].[Value],
[t1].[Value] DESC
still there is another option to use single connection for both min and max queries (see Multiple Active Result Sets (MARS))
or stored procedure..
I'm not sure how to translate it into C# yet (I'm working on it)
This is the Haskell version
minAndMax :: Ord a => [a] -> (a,a)
minAndMax [x] = (x,x)
minAndMax (x:xs) = (min a x, max b x)
where (a,b) = minAndMax xs
The C# version should involve Aggregate some how (I think).
You could select the whole table, and do your min and max operations in memory:
var cache = // select *
var min = cache.Min(...);
var max = cache.Max(...);
Depending on how large your dataset is, this might be the way to go about not hitting your database more than once.
A LINQ to SQL query is a single expression. Thus, if you can't express your query in a single expression (or don't like it once you do) then you have to look at other options.
Stored procedures, since they can have statements, enable you to accomplish this in a single round-trip. You will either have two output parameters or select a result set with two rows. Either way, you will need custom code to read the stored procedure's result.
(I don't personally see the need to avoid two round-trips here. It seems like a premature optimization, especially since you will probably have to jump through hoops to get it working. Not to mention the time you will spend justifying this decision and explaining the solution to other developers.)
Put another way: you've already answered your own question. "I can't use the .Min without grouping first", followed by "that crazy group clause seems silly, and the SQL it makes is more complex than it needs to be", are clues that the simple and easily-understood two-round-trip solution is the best expression of your intent (unless you write custom SQL).

Categories

Resources