【问题标题】:Linq advanced queries with multiple columns具有多列的 Linq 高级查询
【发布时间】:2014-10-15 23:27:09
【问题描述】:

在我的 ASP.NET 项目中,我有一个名为 BrowserStats 的数据表,其中包含不同用户的不同浏览器列表。 我想按用户 ID 对用户进行分组,并使用 linq 显示特定浏览器(Chrome、Firefox、IE)的访问次数。
我的数据表(BrowserStats)如下:

用户名 |浏览器 ---------------------------- 1 | Chrome-32.0 1 | Chrome-30.0 1 | Chrome-33.0 1 |火狐-20.0 1 |火狐-26.0 1 |苹果浏览器 1 | IE-9 1 | IE-10 2 | Chrome-31.0 2 | Chrome-32.0 2 | IE-10 2 |火狐-22.0 2 |火狐-26.0

我的输出表应该是:

用户名 |铬 |火狐 |浏览器 |其他 ----------------------------------------------------------- 1 | 3 | 2 | 2 | 1 2 | 2 | 2 | 1 | 0
  1. 如何在 linq 中查询此输出?
  2. linq 是一种更快的方法,还是我应该在数据库中使用此查询编写一个存储过程并从 C# 调用它?
  3. 有没有关于高级 linq 查询的好教程?

【问题讨论】:

  • 第二个是你应该做的。存储过程是最好的,是的,从 c# 调用它
  • 因此用户在计算机上以及访问网站时有多个浏览器。您记录他们使用的浏览器。稍后您会报告使用情况统计信息。我有这个权利吗?
  • 回答你的第三个问题。你应该在这里观看 Linq 上的视频:youtube.com/user/kudvenkat
  • @RadioSpace 是的。你是对的。
  • @Vishal 我在 youtube 上关注你。提前致谢。

标签: c# sql asp.net linq


【解决方案1】:

您可以在 LINQ 中使用嵌套组:-

var query = from browser in browesers
                        group browser by browser.UserID into UserGroup
                        from countGroup in
                            (from brow in UserGroup
                             group brow by new
                                 {
                                     Chrome = brow.Browser.Contains("Chrome"),
                                     Firefox = brow.Browser.Contains("Firefox"),
                                     IE = brow.Browser.Contains("IE")
                                 } into test
                                     select new
                                     {
                                         ChromeCount = test.Key.Chrome ? test.Count() : 0,
                                         FirefoxCount = test.Key.Firefox ? test.Count() : 0,
                                         IECount = test.Key.IE ? test.Count() : 0,
                                         OthersCount = (!test.Key.Chrome && !test.Key.Firefox && !test.Key.IE) ? test.Count() : 0
                                     }
                                 )
                        group countGroup by UserGroup.Key;

我使用过以下类型:-

public class BrowserInfo
    {
        public int UserID { get; set; }
        public string Browser { get; set; }
    }

这是工作的Fiddle

【讨论】:

    【解决方案2】:

    首先,我认为 LINQ 很慢。 LINQ 几乎是一种嵌套数组迭代逻辑的干净方法。仅在 CPU 必须处理静态数据时使用。或者数据是 CPU 生成的并且没有后备存储。

    反正我就是这么想的。现在来回答:

    我在 SQLServer 2012 Express 中构建了一个数据库,用于 Demon-Striation 目的(

    用户表::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::::::

    浏览器表::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::

    使用表示例(总共 324 行):::::::::::::::::::::::::::::::::::::: :::::::::::::::

    图表:::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::

    PIVOT(我将其添加为存储过程):::::::::::::::::::::::::::::::::::: ::::::::

    VS 2012 / WPF 实现::::::::::::::::::

    在添加存储过程后,将 VS 连接到您的数据库,并将数据集添加到您的项目中。将存储过程拖放到您的数据集中。您也可以在没有类型化数据集生成器的情况下使用存储过程。 See Here

    WPF XAML::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::::::::::

    <Window x:Class="WPFPIVOT.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid Name="datagrid" ItemsSource="{Binding}"/>
    </Grid>
    </Window>
    

    .cs::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    
    namespace WPFPIVOT
    {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Pivot pivoted;
        PivotTableAdapters.GetUsageTableAdapter adapter;
    
    
        public MainWindow()
        {
            InitializeComponent();
    
            //this code is the same for WPF and FORMs
            pivoted = new Pivot();
            adapter = new PivotTableAdapters.GetUsageTableAdapter();
            adapter.Fill(pivoted.GetUsage);
            ///////////////////////////////////////////////////////////////
    
    
            datagrid.DataContext = pivoted;
        }
    
    
    }
    }
    

    WPF 窗口:::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::::

    (UserID 列默认为最右边的列,select 语句可能是select p1.UserID,p1[1],... p.[n]

    【讨论】:

    • 你可以为这个解决方案编写带有 pivot 的 linq 查询吗?
    • @NutBoltu 如果我真的愿意,我可以。但如果你有兴趣,那里有很多例子。检查这个SO QUESTION
    • 好的,谢谢。我想我解决了 :) 感谢分享枢轴概念。
    • @NutBoltu 如果您找到了解决方案,您应该在此处发布答案。所以你回答你自己的问题。这在堆栈中很好。我很好奇你是怎么解决的。
    【解决方案3】:

    如果您想使用 LINQ。它动态地将列和行添加到数据表。输出为数据表格式

    DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[] { new DataColumn("Browser", Type.GetType("System.String")), new DataColumn("userid", Type.GetType("System.String")) });
            dt.Rows.Add(new object[] {"Chrome-32.0","1" });
            dt.Rows.Add(new object[] { "Chrome-32.0", "1" });
            dt.Rows.Add(new object[] { "Firefox-20.0", "1" });
            dt.Rows.Add(new object[] { "Firefox-26.0", "1" });
            dt.Rows.Add(new object[] { "Safari", "1" });
            dt.Rows.Add(new object[] { "IE-9", "1" });
            dt.Rows.Add(new object[] { "IE-10", "1" });
            dt.Rows.Add(new object[] { "Chrome-31.0", "2" });
            dt.Rows.Add(new object[] { "Chrome-32.0", "1" });
            dt.Rows.Add(new object[] { "IE-10", "1" });
            dt.Rows.Add(new object[] { "Firefox-22.0", "2" });
    
            DataTable dtOutPut = new DataTable();
            dtOutPut.Columns.Add(new DataColumn("UserID", Type.GetType("System.String")));
            var tableColumnName = dt.AsEnumerable().Select(s => s.Field<string>("Browser").Trim().ToLower().Split('-')[0].Trim()).Distinct();
            foreach (var item in tableColumnName)
            {
                dtOutPut.Columns.Add(new DataColumn(item, Type.GetType("System.String")));
            }
    
            var usrid = dt.AsEnumerable().Select(s => s.Field<string>("userid").Trim()).Distinct();
    
            Parallel.ForEach(usrid, (s) => {
    
                DataRow rec = dtOutPut.NewRow();
                rec["UserID"] = s;
                foreach (var item in tableColumnName)
                {
                    rec[item] = dt.AsEnumerable().Where(s1 => s1.Field<string>("Browser").Trim().ToLower().Contains(item) && s1.Field<string>("userid") == s).Count();
    
                }
    
                dtOutPut.Rows.Add(rec);
            });
    

    输出:

    【讨论】:

    • 其实数据库来自MS-SQL。我需要一个输出表的linq查询。
    • 哇!这很棒!从没想过在 SQL 之外使用 DataTables 使用 t-sql{declare @tablename table(col1 type,col2 type)}。这是我的回答和拉胡尔的回答之间的一个很好的桥梁。如果这三个都可以一起使用,我认为可以为这种情况产生一种非常巧妙而强大的方法。
    猜你喜欢
    • 2022-01-27
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多