• Aug 15 Sun 2010 21:25
  • 搬家

由於我的部落格一直沒什麼人氣,所以只好搬家到點部落~~未來有新文章會改po在這裡

 

AnferneeHardaway 發表在 痞客邦 留言(0) 人氣()

考題又來了,想 SQL Statment 真的是有活化腦細胞的作用,這次題目如下:

假設有一個 TABLE 欄位如下:   日期, 學生編號, 學生姓名, 成績,可能每隔幾天有一次考試並登入成績。
請問要如何下一個SQL SELECT 查出 每個月 前5名的學生及成績?
(用單月累積 分數最高者為當月第一名)

 

資料表如下(以#Tmp為主,#Name只是用來產生資料而已):

CREATE TABLE #Name(ID INT,Name NVARCHAR(10))
INSERT INTO #Name VALUES(1,'索隆')
INSERT INTO #Name VALUES(2,'喬巴')
INSERT INTO #Name VALUES(3,'娜美')
INSERT INTO #Name VALUES(4,'烏索普')
INSERT INTO #Name VALUES(5,'香吉')
INSERT INTO #Name VALUES(6,'布魯克')
INSERT INTO #Name VALUES(7,'路飛')
INSERT INTO #Name VALUES(8,'羅賓')
INSERT INTO #Name VALUES(9,'佛朗基')
INSERT INTO #Name VALUES(10,'艾斯')
INSERT INTO #Name VALUES(11,'傑克')
INSERT INTO #Name VALUES(12,'雷利')


CREATE TABLE #Tmp ([Date] DATETIME, ID INT, Name NVARCHAR(10), Score INT)
DECLARE @COUNT INT
SET @COUNT = 0

WHILE @COUNT < 1000
BEGIN
INSERT INTO #Tmp
SELECT TOP 1
'2010/' +
CONVERT(VARCHAR(2),CONVERT(INT,RAND()*12+1))
+ '/' +
CONVERT(VARCHAR(2),CONVERT(INT,RAND()*28+1)),
ID,
Name,
CONVERT(INT,RAND()*100+1)
FROM #Name
ORDER BY NEWID()

SET @COUNT += 1
END

DROP TABLE #Name

 

 

 

結果要長得像這樣:

 

image

 

 

 

 

 

 

 

 

 

 

 

我是這樣寫的:

 

WITH CTE AS (
SELECT DATEPART(MONTH,A.[Date]) AS [Month],SUM(A.Score) AS TotalScore,A.ID,A.Name
FROM #Tmp A
GROUP BY A.ID,A.Name,DATEPART(MONTH,A.[Date])
)
SELECT * FROM (
SELECT *,(SELECT COUNT(*) FROM CTE A WHERE A.[Month]=CTE.[Month] AND A.TotalScore>=CTE.TotalScore) AS Grade
FROM CTE
) A
WHERE Grade<= 5
ORDER BY [Month],TotalScore DESC



DROP TABLE #Tmp

AnferneeHardaway 發表在 痞客邦 留言(0) 人氣()

最近有個格式化字串的需求,是要計算已知字串的 Byte 數量,每 100 個 Byte 加上一個換行符號(不能超過100)。一開始的想法是一個 char 一個 char 去跑迴圈並計算 Byte 數。不過這樣又似乎不太妥當,想來想去,最後寫成這個樣子:

public static string SetupType(string text) {
//先去除換行字元
text = text.Replace("\r", "").Replace("\n", "");

//每行最大 Byte 數
int bytesCountEachLine = 100;

//記錄目前已處理完成的字元數
int charIndex = 0;

//最後的回傳值
string result = string.Empty;

Encoding ansi
= Encoding.Default;
byte[] textBytes = ansi.GetBytes(text);

while (charIndex < text.Length) {
//起始位置
int start = ansi.GetByteCount(text.Substring(0, charIndex)) ;

//利用 Encoding.GetCharCount 從起始位置將 100 個 Bytes 的字元一次取出
int count = 0;

if (textBytes.Length - start > bytesCountEachLine)
count
= ansi.GetCharCount(textBytes, start, bytesCountEachLine);
else
count
= ansi.GetCharCount(textBytes, start, textBytes.Length - start);

string target = text.Substring(charIndex, count);

//取出來的字串可能會大於 100 Bytes,所以需要把多餘的去掉
while (ansi.GetByteCount(target) > bytesCountEachLine) {
target
= target.Substring(0, target.Length - 1);
count
-= 1;
}

charIndex
+= count;


//最後一行不用加斷行符號
if (charIndex < text.Length)
result
+= target + "\r\n";
else
result
+= target;
}

return result;
}
 
 
用一段以前很愛看的小說片段來測試,結果如下:
測試前:
image 
 
 
測試後:
image 

AnferneeHardaway 發表在 痞客邦 留言(0) 人氣()

平常用 Visual Studio 新增檔案的時候(例如:aspx、cs...),Visual Studio都會很聰明的產生出一模一樣的檔案,例如下面這張圖:

image

 

其實這是因為 Visual Studio 產生檔案時,是從一堆 Template 當中複製過來的。以上面這張圖為例,是在:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplatesCache\Web\CSharp\1033\WebForm.zip\CodeBeside.cs

 

所以如果希望檔案一產生出來就能夠有一些程式碼的話 (例如:加屬性、繼承其它類別...),可以直接修改這個檔案。

 

其它類型的檔案 Template 也能在這個路徑底下的子目錄找到:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplatesCache

AnferneeHardaway 發表在 痞客邦 留言(0) 人氣()

剛剛看到天才少年 laneser 寫了一段程式碼,為方便說明,我稍微刪掉了一些。大致上如下:

[STAThread]
static unsafe void Main() {
string s = "123";

fixed (char* ps = s) {
ps[
0] = '3';
ps[
1] = '2';
ps[
2] = '1';
}

MessageBox.Show(
"123");
}

 

 

 

得到的結果是這樣 

image

  

 

呵~很有趣吧!其實原理不難,主要是因為 .NET 的 String 型別是不可變動的 (Immutable),因此為了節省記憶體的使用,CLR 會建立一個保留集區 (Intern Pool) 來存放字串。當程式中使用字串時,CLR會先檢查保留集區,有的話就傳回保留集區內的參考;沒有的話,就把字串加到保留集區內,再傳回參考。

 

 

所以上述程式碼其實是這樣執行的:


image

 

 

  

 

天才少年的這段程式碼實在太有趣了!

AnferneeHardaway 發表在 痞客邦 留言(1) 人氣()

最近在MVC上使用AjaxControlToolKit,稍微研究了一下$create()的用法,在這邊做個心得分享:

Note:在MVC上使用AjaxControlToolKit的方法可參考這裡

以下節錄自MSDN的說明:

image

 

我個人的理解如下:

type:元件的型別,可以從對應的 js 檔中找到,例如下圖

image

 

properties:替此元件加入屬性值,例如 id。

events:替此元件的事件加上 handler 。

references:這個很難看出它到底在幹嘛,還好這邊有比較清楚的說明。

element:實體的 DOM 物件。

 

 

最後,舉一個 FilteredTextBox 及 Calendar 的例子:

$create(
AjaxControlToolkit.FilteredTextBoxBehavior,
{
FilterType:AjaxControlToolkit.FilterTypes.Numbers,
id:
"filter1"
},
null,
null,
$get(
"TextBox1")
);

$create(
AjaxControlToolkit.CalendarBehavior,
{ id:
"calendar1" },
{
dateSelectionChanged:
function() {
alert(
"date changed");
}
},
null,
$get(
"TextBox1")
);

AnferneeHardaway 發表在 痞客邦 留言(0) 人氣()

網友問了個問題:WCF 建立時,服務參考的網址是顯示主機名稱,但他想用 IP 取代主機名稱,這該怎麼做呢?其實還挺簡單的,在 IIS 設定一下就行了,下面用對照的方式來看:

 

設定前:

wcf-hostname

 

 

設定後:

wcf-ip

 

 

至於設定什麼呢……其實就是這個:

wcf-ip-instead-hostname

AnferneeHardaway 發表在 痞客邦 留言(0) 人氣()

這個問題存在好久了,每次在家裡用Fiddler都攔截不到瀏覽器所送出的HttpRequest資訊。由於在家寫程式多半都不是為了工作,所以也就睜一隻眼閉一隻眼,攔截不到就攔截不到,程式寫得高興就好。

結果今天為了抓某隻程式所發出的HttpRequest,走投無路之下只好乖乖想辦法排除問題,笨笨的試了一個多小時,最後才在官網上看到解決辦法。如下圖般設定就行囉!

fiddler

AnferneeHardaway 發表在 痞客邦 留言(0) 人氣()

        之前發過一篇 SessionID重複 的問題。事隔多日,總算讓我找到好方法,可以透過修改機碼的方式來改變 IE 共用 SessionID 的行為。

        只要在 HKCU\Software\Microsoft\Internet Explorer\Main 底下新增一個名為 TabProcGrowth 的 DWORD 值,並將其值設為 0 即可。

REG-TabProcGrowth

 

        設定完成後,每個 IE 都會視同使用「新增工作階段」的方式來運作。也就不會有SessionID重複的情況發生了。

AnferneeHardaway 發表在 痞客邦 留言(0) 人氣()

        在網路上看到這個問題,寫起來還挺有趣的,所以記錄一下,避免老了腦袋不靈光,有興趣的朋友不如也來考考自己。

問題如下:

有一個 Table 記載著每位學生每科得的等第,等第由0到5

CREATE TABLE #Test (
    STID INT, Math INT, Social INT, 
    Nature INT, English INT, Chinese INT, 
    Music INT, Physic INT, Work INT,
)
go
INSERT INTO #Test 
VALUES
    (9001, 5, 3, 3, 1, 0, 4, 1, 2),
    (9002, 0, 2, 3, 5, 1, 4, 5, 1),
    (9003, 3, 3, 4, 4, 4, 4, 2, 4),
    (9004, 2, 4, 4, 3, 5, 2, 5, 4),
    (9005, 4, 3, 1, 2, 4, 2, 5, 1),
    (9006, 4, 3, 5, 3, 5, 2, 3, 5),
    (9007, 0, 4, 1, 5, 0, 2, 5, 2),
    (9008, 3, 5, 3, 1, 5, 4, 3, 5),
    (9009, 3, 5, 5, 4, 4, 1, 3, 4),
    (9010, 3, 4, 3, 2, 4, 0, 3, 0),
    (9011, 5, 1, 1, 4, 3, 0, 0, 3),
    (9012, 2, 2, 1, 3, 1, 1, 5, 2),
    (9013, 4, 1, 4, 4, 3, 0, 0, 4),
    (9014, 3, 3, 5, 0, 5, 2, 1, 1),
    (9015, 2, 4, 0, 5, 3, 1, 0, 1)
go


試計算各科每個等第的人數,如下表

Level Math Social Nature English Chinese Music Physic Work
0 2 0 1 1 2 3 3 1
1 0 2 4 1 2 3 1 4
2 3 1 0 2 0 5 1 2
3 4 3 2 3 3 0 4 1
4 3 3 1 3 3 1 0 2
5 1 2 3 2 3 0 2 2

 

 

 

 

 

 

 

 

以下是我的三腳貓解法

 

CREATE TABLE #list(Seq INT)
INSERT INTO #list VALUES(0),(1),(2),(3),(4),(5)
go 
SELECT  Seq AS [Level],
        SUM(CASE WHEN Math = Seq THEN 1 ELSE 0 END) AS Math, 
        SUM(CASE WHEN Social = Seq THEN 1 ELSE 0 END) AS Social,
        SUM(CASE WHEN Nature = Seq THEN 1 ELSE 0 END) AS Nature,
        SUM(CASE WHEN English = Seq THEN 1 ELSE 0 END) AS English,
        SUM(CASE WHEN Chinese = Seq THEN 1 ELSE 0 END) AS Chinese,
        SUM(CASE WHEN Music = Seq THEN 1 ELSE 0 END) AS Music,
        SUM(CASE WHEN Physic = Seq THEN 1 ELSE 0 END) AS Physic,
        SUM(CASE WHEN Work = Seq THEN 1 ELSE 0 END) AS Work
FROM #Test test
CROSS JOIN #list 
GROUP BY Seq

 

 

 

題外話,這個貼程式碼的 plugin 實在太正點了!

 

[2010/4/21] Hunterpo帥氣的露了一手高招,程式碼如下:

CREATE TABLE #t 
(
    STID INT NOT NULL, 
    Math INT NOT NULL, 
    Social INT NOT NULL, 
    Nature INT NOT NULL, 
    English INT NOT NULL, 
    Chinese INT NOT NULL, 
    Music INT NOT NULL, 
    Physic INT NOT NULL, 
    Work INT NOT NULL
)
GO

INSERT INTO #t VALUES(9001, 5, 3, 3, 1, 0, 4, 1, 2);
INSERT INTO #t VALUES(9002, 0, 2, 3, 5, 1, 4, 5, 1);
INSERT INTO #t VALUES(9003, 3, 3, 4, 4, 4, 4, 2, 4);
INSERT INTO #t VALUES(9004, 2, 4, 4, 3, 5, 2, 5, 4);
INSERT INTO #t VALUES(9005, 4, 3, 1, 2, 4, 2, 5, 1);
INSERT INTO #t VALUES(9006, 4, 3, 5, 3, 5, 2, 3, 5);
INSERT INTO #t VALUES(9007, 0, 4, 1, 5, 0, 2, 5, 2);
INSERT INTO #t VALUES(9008, 3, 5, 3, 1, 5, 4, 3, 5);
INSERT INTO #t VALUES(9009, 3, 5, 5, 4, 4, 1, 3, 4);
INSERT INTO #t VALUES(9010, 3, 4, 3, 2, 4, 0, 3, 0);
INSERT INTO #t VALUES(9011, 5, 1, 1, 4, 3, 0, 0, 3);
INSERT INTO #t VALUES(9012, 2, 2, 1, 3, 1, 1, 5, 2);
INSERT INTO #t VALUES(9013, 4, 1, 4, 4, 3, 0, 0, 4);
INSERT INTO #t VALUES(9014, 3, 3, 5, 0, 5, 2, 1, 1);
INSERT INTO #t VALUES(9015, 2, 4, 0, 5, 3, 1, 0, 1);
GO

-- 利用 CTE
WITH unpvt AS
(
    -- 反轉置
    SELECT STID, [Subject], [Level]
    FROM (
        SELECT STID, Math, Social, Nature, English, Chinese, Music, Physic, Work
        FROM #t
    ) AS t
    UNPIVOT (
        [Level] FOR [Subject] IN 
        (Math, Social, Nature, English, Chinese, Music, Physic, Work)
    ) AS unpvt
), pvt AS (
    -- 轉置
    SELECT [Level], Math, Social, Nature, English, Chinese, Music, Physic, Work
    FROM (
        -- 彙總(計算人數)
        SELECT [Subject], [Level], COUNT(STID) AS Counter
        FROM unpvt
        GROUP BY [Subject], [Level]
    ) AS src
    PIVOT
    (
        SUM(Counter) FOR [Subject] IN
        (Math, Social, Nature, English, Chinese, Music, Physic, Work)
    ) AS pvt
)
SELECT *
FROM pvt;
GO

DROP TABLE #t;
GO

AnferneeHardaway 發表在 痞客邦 留言(0) 人氣()

1 23